home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / dev / misc / ahidev.lha / AHI / Developer / drivers / paula / paula_audio.a < prev    next >
Encoding:
Text File  |  1997-08-04  |  82.0 KB  |  3,756 lines

  1. *** ScR ***
  2.  
  3. *** NOTES ***
  4.  
  5. *  The sampler routines are just for fun. Since interrupts must not be disabled,
  6. * there are lots of clicks.
  7.  
  8. ;------------
  9.  
  10. VERSION        EQU    4
  11. REVISION    EQU    13
  12. DATE    MACRO
  13.         dc.b    "3.8.97"
  14.     ENDM
  15. VERS    MACRO
  16.         dc.b    "paula.audio 4.13"
  17.     ENDM
  18. VSTRING    MACRO
  19.         VERS
  20.         dc.b    " ("
  21.         DATE
  22.         dc.b    ")",13,10,0
  23.     ENDM
  24. VERSTAG    MACRO
  25.         dc.b    0,"$VER: "
  26.         VERS
  27.         dc.b    " ("
  28.         DATE
  29.         dc.b    ")",0
  30.     ENDM
  31.  
  32.     incdir    include:
  33.  
  34.     include    hardware/all.i
  35.  
  36.     include    devices/audio.i
  37.     include    dos/dos.i
  38.     include    exec/exec.i
  39.     include    graphics/gfxbase.i
  40.     include intuition/intuitionbase.i
  41.     include intuition/screens.i
  42.     include    resources/misc.i
  43.     include    resources/card.i
  44.     include    utility/utility.i
  45.     include    utility/hooks.i
  46.  
  47.     include    lvo/cardres_lib.i
  48.     include    lvo/dos_lib.i
  49.     include    lvo/exec_lib.i
  50.     include    lvo/graphics_lib.i
  51.     include    lvo/intuition_lib.i
  52.     include    lvo/utility_lib.i
  53.  
  54.     include    devices/ahi.i
  55.     include    libraries/ahi_sub.i
  56.     include    lvo/ahi_sub_lib.i
  57.  
  58.     include    macros.i
  59.  
  60. DEBUG_DETAIL    SET    0
  61.  
  62. _ciaa        EQU    $bfe001
  63. _ciab        EQU    $bfd000
  64.  
  65. PALFREQ        EQU    3546895
  66. NTSCFREQ    EQU    3579545
  67. MINPER        EQU    62
  68.  
  69. RECORDSAMPLES    EQU    1024
  70.  
  71.  
  72. * paula.audio extra tags
  73. AHIDB_Paula14Bit    EQU    AHIDB_UserBase+0    * Boolean
  74. AHIDB_PaulaTable    EQU    AHIDB_UserBase+1    * Boolean
  75.  
  76.  * paulaBase (private)
  77.     STRUCTURE paulaBase,LIB_SIZE
  78.     UBYTE    pb_Flags
  79.     UBYTE    pb_Pad1
  80.     UWORD    pb_Pad2
  81.     APTR    pb_SysLib
  82.     ULONG    pb_SegList
  83.     APTR    pb_GfxLib
  84.     APTR    pb_UtilLib
  85.     APTR    pb_DosLib
  86.     APTR    pb_IntuiLib
  87.     APTR    pb_MiscResource
  88.     APTR    pb_CardResource
  89.     LABEL    paulaBase_SIZEOF
  90.  
  91.  * paula (private) ahiac_DriverData points to this structure.
  92.     STRUCTURE paula,0
  93.     UBYTE    p_Flags
  94.     UBYTE    p_Parallel            ;TRUE if parport allocated
  95.     UWORD    p_DisableCount            ;AHIsub_Enable/AHIsub_Disable cnt
  96.  
  97.     ULONG    p_MinBufferLength
  98.     APTR    p_DMAbuffer            ;Chipmem play buffer
  99.     APTR    p_CalibrationTable
  100.  
  101.     ULONG    p_DoubleBufferOffset
  102.  
  103.     UWORD    p_SwapChannels
  104.     UWORD    p_Pad1
  105.  
  106. ; Pointers to chipmem play buffer
  107.  
  108.     LABEL    p_AudPtrs
  109.     APTR    p_AudPtr1A
  110.     APTR    p_AudPtr2A
  111.     APTR    p_AudPtr3A
  112.     APTR    p_AudPtr4A
  113.     APTR    p_AudPtr1B
  114.     APTR    p_AudPtr2B
  115.     APTR    p_AudPtr3B
  116.     APTR    p_AudPtr4B
  117.  
  118.     UWORD    p_AudPer
  119.     UWORD    p_OutputVolume
  120.     UWORD    p_MonitorVolume
  121.     UWORD    p_Input
  122.  
  123.     APTR    p_AudioCtrl
  124.  
  125.     APTR    p_audioport
  126.     APTR    p_audioreq
  127.     ULONG    p_audiodev
  128.     APTR    p_ParBitsUser
  129.     APTR    p_ParPortUser
  130.     APTR    p_SerBitsUser
  131.     APTR    p_CardHandle
  132.  
  133.     STRUCT    p_PlayInt,IS_SIZE
  134.     STRUCT    p_PlaySoftInt,IS_SIZE
  135.     STRUCT    p_RecInt,IS_SIZE
  136.     STRUCT    p_RecSoftInt,IS_SIZE
  137.  
  138.     ULONG    p_LoopTimes
  139.  
  140.     LABEL    p_PlayerHookRegs
  141.     APTR    p_PlayerHook
  142.     ULONG    p_Reserved
  143.     FPTR    p_PlayerEntry            ;p_PlayerHook->h_Entry
  144.  
  145.     LABEL    p_MixHookRegs
  146.     APTR    p_MixHook
  147.     APTR    p_Mixbuffer
  148.     FPTR    p_MixEntry            ;p_MixHook->h_Entry
  149.  
  150.     LABEL    p_RecIntDataAura
  151.     APTR    p_AuraAddress
  152.  
  153.     LABEL    p_RecIntData
  154.     APTR    p_RecFillPtr
  155.     UWORD    p_RecFillCount
  156.     UWORD    p_Pad2
  157.     APTR    p_RecBuffer1
  158.     APTR    p_RecBuffer2
  159.     APTR    p_RecSoftIntPtr
  160.  
  161.     LABEL    p_RecordMessage
  162.     ULONG    p_rmType
  163.     APTR    p_rmBuffer
  164.     ULONG    p_rmLength
  165.  
  166.     STRUCT    p_CalibrationArray,256
  167.     LABEL    paula_SIZEOF
  168.  
  169. * p_Flags
  170.     BITDEF    P,14BIT,0
  171.     BITDEF    P,HIFI,1
  172. PB_STEREO    EQU    AHIACB_STEREO        ;=2
  173. PF_STEREO    EQU    AHIACF_STEREO
  174.  
  175. Start:
  176.     moveq    #-1,d0
  177.     rts
  178.  
  179. RomTag:
  180.     DC.W    RTC_MATCHWORD
  181.     DC.L    RomTag
  182.     DC.L    EndCode
  183.     DC.B    RTF_AUTOINIT
  184.     DC.B    VERSION                ;version
  185.     DC.B    NT_LIBRARY
  186.     DC.B    0                ;pri
  187.     DC.L    LibName
  188.     DC.L    IDString
  189.     DC.L    InitTable
  190.  
  191. LibName:    dc.b    "paula.audio",0
  192. IDString:    VSTRING
  193. gfxName:    GRAPHICSNAME
  194. utilName:    UTILITYNAME
  195. dosName:    DOSNAME
  196. intuiName:    dc.b    "intuition.library",0
  197. miscName:    MISCNAME
  198. cardName:    dc.b    "card.resource",0
  199. filterVar:    dc.b    "AHIpaulaFilterFreq",0
  200. screenVar:    dc.b    "AHIpaulaSampleLimit",0
  201. bufferVar:    dc.b    "AHIpaulaBufferLength",0
  202. swapVar:    dc.b    "AHIpaulaSwapChannels",0
  203.     cnop    0,2
  204.  
  205. InitTable:
  206.     DC.L    paulaBase_SIZEOF
  207.     DC.L    funcTable
  208.     DC.L    dataTable
  209.     DC.L    initRoutine
  210.  
  211. funcTable:
  212.     dc.l    Open
  213.     dc.l    Close
  214.     dc.l    Expunge
  215.     dc.l    Null
  216. *
  217.     dc.l    AHIsub_AllocAudio
  218.     dc.l    AHIsub_FreeAudio
  219.     dc.l    AHIsub_Disable
  220.     dc.l    AHIsub_Enable
  221.     dc.l    AHIsub_Start
  222.     dc.l    AHIsub_Update
  223.     dc.l    AHIsub_Stop
  224.     dc.l    AHIsub_SetVol
  225.     dc.l    AHIsub_SetFreq
  226.     dc.l    AHIsub_SetSound
  227.     dc.l    AHIsub_SetEffect
  228.     dc.l    AHIsub_LoadSound
  229.     dc.l    AHIsub_UnloadSound
  230.     dc.l    AHIsub_GetAttr
  231.     dc.l    AHIsub_HardwareControl
  232.     dc.l    -1
  233.  
  234. dataTable:
  235.     INITBYTE    LN_TYPE,NT_LIBRARY
  236.     INITLONG    LN_NAME,LibName
  237.     INITBYTE    LIB_FLAGS,LIBF_SUMUSED|LIBF_CHANGED
  238.     INITWORD    LIB_VERSION,VERSION
  239.     INITWORD    LIB_REVISION,REVISION
  240.     INITLONG    LIB_IDSTRING,IDString
  241.     DC.L        0
  242.  
  243. initRoutine:
  244.     movem.l    d1/a0/a1/a5/a6,-(sp)
  245.     move.l    d0,a5
  246.     move.l    a6,pb_SysLib(a5)
  247.     move.l    a0,pb_SegList(a5)
  248.     lea    gfxName(pc),a1
  249.     moveq    #0,d0
  250.     call    OpenLibrary
  251.     move.l    d0,pb_GfxLib(a5)
  252.     bne.b    .gfxOK
  253.     ALERT    AG_OpenLib|AO_GraphicsLib
  254.     moveq    #0,d0
  255.     bra    .exit
  256. .gfxOK
  257.     lea    utilName(pc),a1
  258.     moveq    #0,d0
  259.     call    OpenLibrary
  260.     move.l    d0,pb_UtilLib(a5)
  261.     bne.b    .utilOK
  262.     ALERT    AG_OpenLib|AO_UtilityLib
  263.     moveq    #0,d0
  264.     bra    .exit
  265. .utilOK
  266.     lea    dosName(pc),a1
  267.     moveq    #0,d0
  268.     call    OpenLibrary
  269.     move.l    d0,pb_DosLib(a5)
  270.     bne.b    .dosOK
  271.     ALERT    AG_OpenLib|AO_DOSLib
  272.     moveq    #0,d0
  273.     bra    .exit
  274. .dosOK
  275.     lea    intuiName(pc),a1
  276.     moveq    #0,d0
  277.     call    OpenLibrary
  278.     move.l    d0,pb_IntuiLib(a5)
  279.     bne.b    .intuiOK
  280.     ALERT    AG_OpenLib|AO_Intuition
  281.     moveq    #0,d0
  282.     bra    .exit
  283. .intuiOK
  284.     lea    miscName(pc),a1
  285.     call    OpenResource
  286.     move.l    d0,pb_MiscResource(a5)
  287.     bne.b    .miscOK
  288.     ALERT    AG_OpenRes|AO_MiscRsrc
  289.     moveq    #0,d0
  290.     bra    .exit
  291. .miscOK
  292.     lea    cardName(pc),a1
  293.     call    OpenResource
  294.     move.l    d0,pb_CardResource(a5)        ;Don't fail on error
  295.  
  296.     move.l    a5,d0
  297. .exit
  298.     movem.l    (sp)+,d1/a0/a1/a5/a6
  299.     rts
  300.  
  301. Open:
  302.     moveq    #0,d0
  303.     addq.w    #1,LIB_OPENCNT(a6)
  304.     bclr.b    #LIBB_DELEXP,pb_Flags(a6)
  305.     move.l    a6,d0
  306. .exit
  307.     rts
  308.  
  309. Close:
  310.     moveq    #0,d0
  311.     subq.w    #1,LIB_OPENCNT(a6)
  312.     bne.b    .exit
  313.     btst.b    #LIBB_DELEXP,pb_Flags(a6)
  314.     beq.b    .exit
  315.     bsr    Expunge
  316. .exit
  317.     rts
  318.  
  319. Expunge:
  320.     movem.l    d1/d2/a0/a1/a5/a6,-(sp)
  321.     move.l    a6,a5
  322.     move.l    pb_SysLib(a5),a6
  323.     tst.w    LIB_OPENCNT(a5)
  324.     beq.b    .notopen
  325.     bset.b    #LIBB_DELEXP,pb_Flags(a5)
  326.     moveq    #0,d0
  327.     bra.b    .Expunge_end
  328. .notopen
  329.     move.l    pb_IntuiLib(a5),a1
  330.     call    CloseLibrary
  331.  
  332.     move.l    pb_DosLib(a5),a1
  333.     call    CloseLibrary
  334.  
  335.     move.l    pb_UtilLib(a5),a1
  336.     call    CloseLibrary
  337.  
  338.     move.l    pb_GfxLib(a5),a1
  339.     call    CloseLibrary
  340.  
  341.     move.l    pb_SegList(a5),d2
  342.     move.l    a5,a1
  343.     call    Remove
  344.  
  345.     moveq    #0,d0
  346.     move.l    a5,a1
  347.     move.w    LIB_NEGSIZE(a5),d0
  348.     sub.l    d0,a1
  349.     add.w    LIB_POSSIZE(a5),d0
  350.     call    FreeMem
  351.     move.l    d2,d0
  352. .Expunge_end
  353.     movem.l    (sp)+,d1/d2/a0/a1/a5/a6
  354.     rts
  355.  
  356. Null:
  357.     moveq    #0,d0
  358.     rts
  359.  
  360. * BeginIO(ioRequest)(a1) (From amiga.lib)
  361. BeginIO:
  362.     move.l    a1,a0        ;probably not neccesary
  363.     push    a6
  364.     move.l    IO_DEVICE(a1),a6
  365.     jsr    -30(a6)
  366.     pop    a6
  367.     rts
  368.  
  369. ****** [driver].audio/--background-- ****************************************
  370. *
  371. *   OVERVIEW
  372. *
  373. *       DRIVER VERSIONS
  374. *
  375. *       The lowest supported driver version is 2. If you use any feature
  376. *       introduced in later versions of AHI, you should set the driver
  377. *       version to the same version as the features were introduced with.
  378. *       Example: You use PreTimer() and PostTimer(), and since these
  379. *       calls were added in V4 of ahi.device, your driver's version should
  380. *       be 4, too.
  381. *
  382. *       AUDIO ID NUMBERS
  383. *
  384. *       Just some notes about selecting ID numbers for different modes:
  385. *       It is up to the driver programmer to chose which modes should be
  386. *       available to the user. Take care when selecting.
  387. *
  388. *       The upper word is the hardware ID, and can only be allocated by
  389. *       Martin Blom <lcs@lysator.liu.se>. The lower word is free, but in
  390. *       order to allow enhancements, please only use bit 0 to 3 for modes!
  391. *       If your driver supports multiple sound cards, use bit 12-15 to
  392. *       select card (first one is 0). If your sound card has multiple
  393. *       AD/DA converters, you can use bit 8-11 to select them (the first
  394. *       should be 0).
  395. *
  396. *       Set the remaining bits to zero.
  397. *
  398. *       Use AHI:Developer/Support/ScanAudioModes to have a look at the modes
  399. *       currently available. Use AHI:Developer/Support/sift to make sure your
  400. *       mode descriptor file is a legal IFF file.
  401. *
  402. *       I do reserve the right to change the rules if I find them incorrect!
  403. *
  404. *****************************************************************************
  405. *
  406. *
  407.  
  408. ****** [driver].audio/AHIsub_AllocAudio *************************************
  409. *
  410. *   NAME
  411. *       AHIsub_AllocAudio -- Allocates and initializes the audio hardware.
  412. *
  413. *   SYNOPSIS
  414. *       result = AHIsub_AllocAudio( tags, audioctrl);
  415. *       D0                          A1    A2
  416. *
  417. *       ULONG AHIsub_AllocAudio( struct TagItem *, struct AHIAudioCtrlDrv * );
  418. *
  419. *   IMPLEMENTATION
  420. *       Allocate and initialize the audio hardware. Decide if and how you
  421. *       wish to use the mixing routines provided by 'ahi.device', by looking
  422. *       in the AHIAudioCtrlDrv structure and parsing the tag list for tags
  423. *       you support.
  424. *
  425. *       1) Use mixing routines with timing:
  426. *           You will need to be able to play any number of samples from
  427. *           about 80 up to 65535 with low overhead.
  428. *           · Update AudioCtrl->ahiac_MixFreq to nearest value that your
  429. *             hardware supports.
  430. *           · Return AHISF_MIXING|AHISF_TIMING.
  431. *       2) Use mixing routines without timing:
  432. *           If the hardware can't play samples with any length, use this
  433. *           alternative and provide timing yourself. The buffer must
  434. *           take less than about 20 ms to play, preferable less than 10!
  435. *           · Update AudioCtrl->ahiac_MixFreq to nearest value that your
  436. *             hardware supports.
  437. *           · Store the number of samples to mix each pass in
  438. *             AudioCtrl->ahiac_BuffSamples.
  439. *           · Return AHISF_MIXING
  440. *           Alternatively, you can use the first method and call the
  441. *           mixing hook several times in a row to fill up a buffer.
  442. *           In that case, AHIsub_GetAttr(AHIDB_MaxPlaySamples) should
  443. *           return the size of the buffer plus AudioCtrl->ahiac_MaxBuffSamples.
  444. *           If the buffer is so large that it takes more than (approx.) 10 ms to
  445. *           play it for high sample frequencies, AHIsub_GetAttr(AHIDB_Realtime)
  446. *           should return FALSE.
  447. *       3) Don't use mixing routines:
  448. *           If your hardware can handle everything without using the CPU to
  449. *           mix the channels, you tell 'ahi.device' this by not setting
  450. *           either the AHISB_MIXING or the AHISB_TIMING bit.
  451. *
  452. *       If you can handle stereo output from the mixing routines, also set
  453. *       bit AHISB_KNOWSTEREO.
  454. *
  455. *       If you can handle hifi (32 bit) output from the mixing routines,
  456. *       set bit AHISB_KNOWHIFI.
  457. *
  458. *       If this driver can be used to record samples, set bit AHISB_CANRECORD,
  459. *       too (regardless if you use the mixing routines in AHI or not).
  460. *
  461. *       If the sound card has hardware to do DSP effects, you can set the
  462. *       AHISB_CANPOSTPROCESS bit. The output from the mixing routines will 
  463. *       then be two separate buffers, one wet and one dry. You should then
  464. *       apply the Fx on the wet buffer, and post-mix the two buffers before
  465. *       you send the samples to the DAC. (V4)
  466. *
  467. *   INPUTS
  468. *       tags - pointer to a taglist.
  469. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  470. *
  471. *   TAGS
  472. *       The tags are from the audio database (AHIDB_#? in <devices/ahi.h>),
  473. *       NOT the tag list the user called ahi.device/AHI_AllocAudio() with.
  474. *
  475. *   RESULT
  476. *       Flags, defined in <libraries/ahi_sub.h>.
  477. *
  478. *   EXAMPLE
  479. *
  480. *   NOTES
  481. *       You don't have to clean up on failure, AHIsub_FreeAudio() will
  482. *       always be called.
  483. *
  484. *   BUGS
  485. *
  486. *   SEE ALSO
  487. *       AHIsub_FreeAudio(), AHIsub_Start()
  488. *
  489. *****************************************************************************
  490. *
  491. *
  492.  
  493. AHIsub_AllocAudio:
  494.     pushm    d2-d7/a2-a6
  495.     move.l    a6,a5
  496.  
  497.     move.l    a1,d3
  498.  
  499. * Allocate the 'paula' structure (our variables)
  500.     move.l    pb_SysLib(a5),a6
  501.     move.l    #paula_SIZEOF,d0
  502.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  503.     call    AllocVec
  504.     move.l    d0,ahiac_DriverData(a2)
  505.     beq    .error_nopaula
  506.     move.l    d0,a3
  507.  
  508. * Initialize some fields...
  509.     move.l    #-1,p_audiodev(a3)
  510.     move.l    #-1,p_ParBitsUser(a3)
  511.     move.l    #-1,p_ParPortUser(a3)
  512.     move.l    #-1,p_SerBitsUser(a3)
  513.     move.l    a2,p_AudioCtrl(a3)
  514.     lea    p_RecSoftInt(a3),a0
  515.     move.l    a0,p_RecSoftIntPtr(a3)
  516.     move.l    #AHIST_S16S,p_rmType(a3)
  517.     move.l    #RECORDSAMPLES,p_rmLength(a3)
  518.     move.w    #64,p_OutputVolume(a3)
  519.  
  520. * Translate tags to flags
  521.     moveq    #0,d2
  522.     move.l    pb_UtilLib(a5),a6
  523.     move.l    #AHIDB_Paula14Bit,d0
  524.     moveq    #0,d1
  525.     move.l    d3,a0                ;tag list
  526.     call    GetTagData
  527.     tst.l    d0
  528.     beq.b    .no14bit
  529.     moveq    #PF_14BIT,d2
  530. .no14bit
  531.     move.l    #AHIDB_HiFi,d0
  532.     moveq    #0,d1
  533.     move.l    d3,a0                ;tag list
  534.     call    GetTagData
  535.     tst.l    d0
  536.     beq.b    .noHiFi
  537.     or.b    #PF_HIFI,d2
  538. .noHiFi
  539.     move.l    ahiac_Flags(a2),d0
  540.     and.b    #PF_STEREO,d0            ;same as AHIACF_STEREO
  541.     or.b    d2,d0
  542.     move.b    p_Flags(a3),d1
  543.     and.b    #~(PF_STEREO|PF_HIFI|PF_14BIT),d1
  544.     or.b    d0,d1
  545.     move.b    d1,p_Flags(a3)
  546.  
  547. * Check if a table should be used (14 bit calibration)
  548.     move.l    #AHIDB_PaulaTable,d0
  549.     moveq    #0,d1
  550.     move.l    d3,a0                ;tag list
  551.     call    GetTagData
  552.     tst.l    d0
  553.     beq    .notable
  554.  
  555. * Load 'ENV:CyberSound/SoundDrivers/14Bit_Calibration', allocate
  556. * and initialize the table.
  557. * FIXIT: The calibration file should move to a special chunk in
  558. * 'DEVS:AudioModes/PAULA'.
  559.     move.l    pb_DosLib(a5),a6
  560.     lea    .calibname(pc),a0
  561.     move.l    a0,d1
  562.     move.l    #MODE_OLDFILE,d2
  563.     call    Open
  564.     move.l    d0,d4
  565.     beq    .nocalib
  566.     move.l    d0,d1
  567.     lea    p_CalibrationArray(a3),a0
  568.     move.l    a0,d2
  569.     move.l    #256,d3
  570.     call    Read
  571.     cmp.l    d0,d3
  572.     beq    .tableloaded
  573. .nocalib
  574. ; Fill defaults
  575.     lea    p_CalibrationArray(a3),a0
  576.     move.w    #254-1,d0
  577. .initcalib
  578.     move.b    #$55,(a0)+
  579.     dbf    d0,.initcalib
  580.     move.b    #$7f,(a0)+
  581. .tableloaded
  582.     move.l    d4,d1
  583.     beq.b    .nofile
  584.     call    Close
  585. .nofile
  586.     move.l    pb_SysLib(a5),a6
  587.     move.l    #65536*2,d0
  588.     move.l    #MEMF_PUBLIC,d1
  589.     call    AllocVec
  590.     move.l    d0,p_CalibrationTable(a3)
  591.     beq.b    .notable
  592.     move.l    d0,a0            ;table
  593.     lea    p_CalibrationArray(a3),a1
  594.     bsr.w    _CreateTable
  595. .notable
  596.  
  597. * Get the minimum chip buffer size
  598.     moveq    #0,d5                ;Default
  599.     move.l    pb_DosLib(a5),a6
  600.     subq.l    #8,sp                ;local label
  601.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  602.     lea    bufferVar(pc),a0
  603.     move.l    a0,d1
  604.     move.l    sp,d2
  605.     moveq.l    #8,d3
  606.     moveq.l    #0,d4
  607.     call    GetVar
  608.     cmp.l    #-1,d0
  609.     beq    .gotlength
  610.     move.l    sp,d1
  611.     pea.l    0.w
  612.     move.l    sp,d2
  613.     call    StrToLong
  614.     move.l    (sp)+,d5
  615. .gotlength
  616.     addq.l    #8,sp
  617. ; d5 is now the buffer length
  618.     move.l    d5,p_MinBufferLength(a3)
  619.  
  620. * Check if we should swap left & right channels
  621.     moveq    #0,d5                ;Default
  622.     move.l    pb_DosLib(a5),a6
  623.     subq.l    #8,sp                ;local label
  624.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  625.     lea    swapVar(pc),a0
  626.     move.l    a0,d1
  627.     move.l    sp,d2
  628.     moveq.l    #8,d3
  629.     moveq.l    #0,d4
  630.     call    GetVar
  631.     cmp.l    #-1,d0
  632.     beq    .gotswap
  633.     move.l    sp,d1
  634.     pea.l    0.w
  635.     move.l    sp,d2
  636.     call    StrToLong
  637.     move.l    (sp)+,d5
  638. .gotswap
  639.     addq.l    #8,sp
  640. ; d5 is now the buffer length
  641.     move.w    d5,p_SwapChannels(a3)
  642.  
  643. * allocate audio.device
  644.     move.l    pb_SysLib(a5),a6
  645.     call    CreateMsgPort
  646.     move.l    d0,p_audioport(a3)
  647.     beq    .error_noport
  648.     moveq    #ioa_SIZEOF,d0
  649.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  650.     call    AllocVec
  651.     move.l    d0,p_audioreq(a3)
  652.     beq    .error_noreqmem
  653.     move.l    d0,a0
  654.     move.l    p_audioport(a3),MN_REPLYPORT(a0)
  655.     clr.w    ioa_AllocKey(a0)
  656.     move.b    #127,LN_PRI(a0)            ;steal it!
  657.     lea    .audiochannelarray(pc),a1
  658.     move.l    a1,ioa_Data(a0)
  659.     move.l    #1,ioa_Length(a0)
  660.     lea    .audioname(pc),a0
  661.     moveq    #0,d0
  662.     move.l    p_audioreq(a3),a1
  663.     moveq    #0,d1
  664.     call    OpenDevice
  665.     move.l    d0,p_audiodev(a3)
  666.     bne    .error_noaudiodev        ;somebody already owns the hardware (could be us!)
  667.     move.l    p_audioreq(a3),a1
  668.     move.w    #CMD_RESET,IO_COMMAND(a1)
  669.     bsr.w    BeginIO                ;clear attach, stop sound.
  670.     move.l    p_audioport(a3),a0
  671.     call    WaitPort
  672.     move.l    p_audioport(a3),a0
  673.     call    GetMsg
  674.  
  675.     move.l    pb_DosLib(a5),a6
  676.     moveq    #1,d1
  677.     call    Delay
  678.  
  679. * test if mode supports recording
  680.     btst    #PB_14BIT,p_Flags(a3)
  681.     bne    .dontgetsampler            ;no record if 14 bit mode
  682.  
  683. * try to allocate parallel port
  684.     clr.b    p_Parallel(a3)
  685.     move.l    pb_MiscResource(a5),a6
  686.     moveq    #MR_PARALLELBITS,d0
  687.     lea    IDString(pc),a1
  688.     jsr    MR_ALLOCMISCRESOURCE(a6)
  689.     move.l    d0,p_ParBitsUser(a3)
  690.     bne    .no_parrallel
  691.     moveq    #MR_PARALLELPORT,d0
  692.     lea    IDString(pc),a1
  693.     jsr    MR_ALLOCMISCRESOURCE(a6)
  694.     move.l    d0,p_ParPortUser(a3)
  695.     bne    .no_parrallel
  696.  
  697.     move.b    #TRUE,p_Parallel(a3)
  698.     move.b    #0,_ciaa+ciaddrb            ;make PB0-PB7 inputs
  699. .no_parrallel
  700.  
  701. * allocate Aura sampler
  702.     clr.l    p_AuraAddress(a3)
  703.     move.l    pb_CardResource(a5),d0
  704.     beq    .no_aura
  705.     move.l    d0,a6
  706.     call    GetCardMap
  707.     tst.l    d0
  708.     beq    .no_aura
  709.     move.l    d0,a0
  710.     move.l    cmm_IOMemory(a0),d2
  711.     beq    .no_aura
  712.  
  713.     move.l    pb_SysLib(a5),a6
  714.     moveq    #CardHandle_SIZEOF,d0
  715.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  716.     call    AllocVec
  717.     move.l    d0,p_CardHandle(a3)
  718.     beq    .no_aura
  719.  
  720.     move.l    pb_CardResource(a5),a6
  721.     move.l    d0,a1
  722.     move.l    #IDString,LN_NAME(a1)
  723.     move.b    #CARDF_RESETREMOVE|CARDF_IFAVAILABLE,cah_CardFlags(a1)
  724.     call    OwnCard
  725.     tst.l    d0
  726.     bne    .no_aura
  727.  
  728.     move.l    p_CardHandle(a3),a1
  729.     call    BeginCardAccess
  730.  
  731.     move.l    d2,p_AuraAddress(a3)
  732. .no_aura
  733. .dontgetsampler
  734.  
  735.  
  736. * initialize interrupts (Only dummy function pointers at this time)
  737.  
  738.  * p_PlayInt (the main playback interrupt)
  739.     move.b    #NT_INTERRUPT,LN_TYPE+p_PlayInt(a3)
  740.     move.l    #LibName,LN_NAME+p_PlayInt(a3)
  741.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  742.     move.l    a3,IS_DATA+p_PlayInt(a3)
  743.  
  744.  * p_PlaySoftInt (caused by p_PlayInt, here are the mixing and conversion done)
  745.     move.b    #NT_INTERRUPT,LN_TYPE+p_PlaySoftInt(a3)
  746.     move.l    #LibName,LN_NAME+p_PlaySoftInt(a3)
  747.     move.l    #SoftInt_Dummy,IS_CODE+p_PlaySoftInt(a3)
  748.     move.l    a3,IS_DATA+p_PlaySoftInt(a3)
  749.  
  750.  * p_RecInt (the interrupt used for recording)
  751.     move.b    #NT_INTERRUPT,LN_TYPE+p_RecInt(a3)
  752.     move.l    #LibName,LN_NAME+p_RecInt(a3)
  753.     move.l    #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
  754.     clr.l    IS_DATA+p_RecInt(a3)
  755.  
  756.  * p_RecSoftInt (caused by p_RecInt when the record buffer has been filled)
  757.     move.b    #32,LN_PRI+p_RecSoftInt(a3)
  758.     move.b    #NT_INTERRUPT,LN_TYPE+p_RecSoftInt(a3)
  759.     move.l    #LibName,LN_NAME+p_RecSoftInt(a3)
  760.     move.l    #RecordSoftInt,IS_CODE+p_RecSoftInt(a3)
  761.     move.l    a3,IS_DATA+p_RecSoftInt(a3)
  762.  
  763. * Make sure no interrupts occur until AHIsub_Start() is called
  764.     move.w    #INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3,custom+INTENA
  765.  
  766. * Update ahiac_MixFreq to what the mixing/sampling frequency really is
  767.     move.l    ahiac_MixFreq(a2),d1
  768.     bsr    calcperiod
  769.     move.l    d0,ahiac_MixFreq(a2)        ;store actual freq
  770.  
  771. * Check the AHIpaulaFilterFreq variable.
  772. * If the mixing frequency is higher than this one, set disable the filter,
  773. * else enable it.
  774.     moveq    #0,d5                ;Default freq
  775.     move.l    pb_DosLib(a5),a6
  776.     subq.l    #8,sp                ;local label
  777.     move.w    #("0"<<8)|0,(sp)        ;Initialize as "0"
  778.     lea    filterVar(pc),a0
  779.     move.l    a0,d1
  780.     move.l    sp,d2
  781.     moveq.l    #8,d3
  782.     moveq.l    #0,d4
  783.     call    GetVar
  784.     cmp.l    #-1,d0
  785.     beq    .gotfreq
  786.     move.l    sp,d1
  787.     pea.l    0.w
  788.     move.l    sp,d2
  789.     call    StrToLong
  790.     move.l    (sp)+,d5
  791. .gotfreq
  792.     addq.l    #8,sp
  793. ; d5 is now the freq
  794.  
  795.     cmp.l    ahiac_MixFreq(a2),d5
  796.     bls    .no_filter
  797.     bclr    #1,$bfe001            ;turn audio filter on
  798.     bra    .filter_set
  799. .no_filter
  800.     bset    #1,$bfe001            ;turn audio filter off
  801. .filter_set
  802.  
  803.     moveq    #AHISF_KNOWSTEREO|AHISF_KNOWHIFI|AHISF_CANRECORD|AHISF_MIXING|AHISF_TIMING,d0
  804. .exit
  805.     popm    d2-d7/a2-a6
  806.     rts
  807.  
  808. .error_noaudiodev
  809. .error_noreqmem
  810. .error_noport
  811. .error_nopaula
  812.     moveq    #AHISF_ERROR,d0
  813.     bra.b    .exit
  814.  
  815. .audiochannelarray
  816.     dc.b    1+2+4+8
  817. .audioname
  818.     AUDIONAME
  819. .calibname
  820.     dc.b    "ENV:CyberSound/SoundDrivers/14Bit_Calibration",0
  821.     even
  822. .cardhandle:
  823.     dc.l    0,0        ;ln_Succ, ln_Pred
  824.     dc.b    0        ;ln_Type
  825.     dc.b    0        ;ln_Pri
  826.     dc.l    IDString    ;ln_Name
  827.     dc.l    0,0,0        ;cah_CardRemoved, cah_CardInserted, cah_CardStatus
  828.     dc.b    (CARDF_RESETREMOVE|CARDF_IFAVAILABLE)
  829.     even
  830.  
  831. ;in:
  832. * d1    MixFreq
  833. * a5    paulaBase
  834. ;out:
  835. * d0    New MixFreq
  836. * d1.w    Period
  837. ;description:
  838. *    Calculate and return the best period and the actual frequency.
  839. calcperiod:
  840.     pushm    d2-d7/a2-a6
  841.     move.l    #PALFREQ,d2            ;PAL
  842.     move.l    pb_GfxLib(a5),a0
  843.     move.w    gb_DisplayFlags(a0),d0
  844.     btst    #REALLY_PALn,d0
  845.     bne.b    .1
  846.     move.l    #NTSCFREQ,d2            ;NTSC
  847. .1
  848.     move.l    d2,d0
  849.     move.l    d1,d3
  850.     move.l    pb_UtilLib(a5),a1
  851.     jsr    _LVOUDivMod32(a1)
  852.     lsl.l    #1,d1
  853.     cmp.l    d3,d1
  854.     bmi.b    .3
  855.     addq.l    #1,d0
  856. .3
  857.     move.w    d0,d4
  858. * d4 is now period. Check if is it a valid one, depending on current display mode
  859.     bsr    checkvideo
  860.     moveq    #MINPER,d1
  861.     tst.l    d0
  862.     bne    .5
  863.     moveq    #MINPER*2,d1
  864. .5
  865.     cmp.w    d1,d4
  866.     bhs.b    .6
  867.     move.w    d1,d4
  868. .6
  869.     moveq    #0,d1
  870.     move.w    d4,d1
  871.     move.l    d2,d0
  872.     move.l    d1,d3
  873.     move.l    pb_UtilLib(a5),a1
  874.     jsr    _LVOUDivMod32(a1)
  875.     lsl.l    #1,d1
  876.     cmp.l    d3,d1
  877.     bmi.b    .4
  878.     addq.l    #1,d0
  879. .4
  880.     move.w    d4,d1
  881.     popm    d2-d7/a2-a6
  882.     rts
  883.  
  884. ;in:
  885. * a5    paulaBase
  886. ;out:
  887. * d0    TRUE if current mode is double
  888. ;description:
  889. *    Checks if the current screen mode is doublescan.
  890. *    This routine is a bit ugly, but it does get the job
  891. *    done, even if a graphic card is used.
  892. checkvideo:
  893.     pushm    d2-d7/a2-a6
  894.  
  895. * Check the AHIpaulaSampleLimit variable.
  896. * If 1, allow > 28 kHz frequencies, if 0, don't. If not present,
  897. * check the screen mode.
  898.     move.l    pb_DosLib(a5),a6
  899.     clr.w    -(sp)                ;Initialize local data
  900.     lea    screenVar(pc),a0
  901.     move.l    a0,d1
  902.     move.l    sp,d2
  903.     moveq.l    #2,d3
  904.     moveq.l    #0,d4
  905.     call    GetVar
  906.     move.w    (sp)+,d1
  907.     cmp.l    #-1,d0
  908.     beq    .testfreq
  909.     cmp.w    #"0"<<8|0,d1
  910.     beq    .no31k
  911.     cmp.w    #"1"<<8|0,d1
  912.     beq    .is31k
  913.  
  914. .testfreq
  915.  
  916. ; Chip revision test
  917.  
  918.     move.l    pb_GfxLib(a5),a0
  919.     move.b    gb_ChipRevBits0(a0),d0
  920.     and.b    #GFXF_HR_DENISE|GFXF_AA_LISA,d0
  921.     beq    .no31k                ; OCS: No 31 kHz modes
  922.  
  923. ; Native screen test
  924.  
  925.     moveq    #0,d0
  926.     move.l    pb_IntuiLib(a5),a6
  927.     call    LockIBase
  928.     move.l    d0,d2
  929.     move.l    ib_FirstScreen(a6),a0
  930.     lea    sc_ViewPort(a0),a0
  931.     move.l    pb_GfxLib(a5),a6
  932.     call    GetVPModeID
  933.     move.l    d2,a0
  934.     move.l    d0,d2
  935.     move.l    pb_IntuiLib(a5),a6
  936.     call    UnlockIBase
  937.  
  938.     ; "Check" if native screen
  939.     move.l    d2,d0
  940.     and.l    #$40000000,d0
  941.     bne    .gfxcard
  942.  
  943.     ; It is!
  944.     sub.w    #mtr_SIZEOF,sp            ;local storage
  945.     suba.l    a0,a0
  946.     move.l    sp,a1
  947.     move.l    #mtr_SIZEOF,d0
  948.     move.l    #DTAG_MNTR,d1
  949.     move.l    pb_GfxLib(a5),a6
  950.     call    GetDisplayInfoData
  951.  
  952.     moveq    #1,d1
  953.     add.w    mtr_TotalRows(sp),d1
  954.     sub.w    mtr_MinRow(sp),d1
  955.     move.w    mtr_TotalColorClocks(sp),d2
  956.     mulu.w    mtr_TotalRows(sp),d2
  957.  
  958.     add.w    #mtr_SIZEOF,sp            ;restore stack
  959.     tst.l    d0
  960.     beq    .no31k
  961.     ; Calculate TotalColorClocks*TotalRows/(2*(TotalRows-MinRow+1)
  962.     add.l    d1,d1
  963.     beq    .no31k
  964.     divu    d1,d2
  965.     cmp.w    #64,d2                ; 64 is an round nice number, no?
  966.     bls    .is31k
  967.     bra    .no31k
  968.  
  969. .gfxcard
  970.  
  971. ; Picasso '96 test
  972.  
  973.     lea    .picasso96(pc),a1
  974.     move.l    pb_SysLib(a5),a6
  975.     call    FindTask
  976.     tst.l    d0
  977.     beq    .cgfx                ; Not P96, assume CyberGraphX
  978.  
  979.     move.l    pb_DosLib(a5),a6
  980.     clr.l    -(sp)                ;Initialize local data
  981.     lea    .p96amigavideo(pc),a0
  982.     move.l    a0,d1
  983.     move.l    sp,d2
  984.     moveq.l    #4,d3
  985.     moveq.l    #0,d4
  986.     call    GetVar
  987.     move.l    (sp)+,d1
  988.     swap.w    d1
  989.     cmp.w    #"31",d1
  990.     beq    .is31k
  991.     bra    .no31k
  992.  
  993. .cgfx
  994.  
  995. ; CybergraphX test
  996.  
  997.     move.l    pb_GfxLib(a5),a0
  998.     cmp.w    #39,LIB_VERSION(a0)
  999.     beq    .known
  1000.     cmp.w    #40,LIB_VERSION(a0)
  1001.     beq    .known
  1002.     bra    .no31k
  1003. .known
  1004.     move.l    gb_copinit(a0),a0
  1005.     cmp.w    #$01FC,copinit_fm0(a0)        ;Security check (test if really FMODE)
  1006.     bne    .is31k                ;Probably an ECS machine.
  1007.                         ;Assume the user is clever enough
  1008.                         ;to use "AddAudioModes DBLSCAN"....
  1009.     move.w    copinit_fm0+2(a0),d0
  1010.     and.w    #$c000,d0            ;Mask sprite and bitplane double bit
  1011.     beq    .no31k
  1012. .is31k
  1013.     moveq    #TRUE,d0
  1014.     bra    .exit
  1015. .no31k
  1016.     moveq    #FALSE,d0
  1017. .exit
  1018.     popm    d2-d7/a2-a6
  1019.     rts
  1020. .picasso96
  1021.     dc.b    "Picasso96",0
  1022. .p96amigavideo
  1023.     dc.b    "Picasso96/AmigaVideo",0
  1024.     even
  1025.  
  1026. ;in:
  1027. * d0    Frequency
  1028. ;out:
  1029. * d0    Closest frequency
  1030. * d1    Index
  1031. findfreq:
  1032.     lea    freqlist(pc),a0
  1033.     cmp.l    (a0),d0
  1034.     bls.b    .2
  1035. .findfreq
  1036.     cmp.l    (a0)+,d0
  1037.     bhi.b    .findfreq
  1038.     move.l    -4(a0),d1
  1039.     sub.l    d0,d1
  1040.     sub.l    -8(a0),d0
  1041.     cmp.l    d1,d0
  1042.     bhs.b    .1
  1043.     subq.l    #4,a0
  1044. .1
  1045.     subq.l    #4,a0
  1046. .2
  1047.     move.l    (a0),d0
  1048.     move.l    a0,d1
  1049.     sub.l    #freqlist,d1
  1050.     lsr.l    #2,d1
  1051.     rts
  1052.  
  1053. freqlist:
  1054.     dc.l    4410                    ; CD/10
  1055.     dc.l    4800                    ; DAT/10
  1056.     dc.l    5513                    ; CD/8
  1057.     dc.l    6000                    ; DAT/8
  1058.     dc.l    7350                    ; CD/6
  1059.     dc.l    8000                    ; µ- and A-Law, DAT/6
  1060.     dc.l    9600                    ; DAT/5
  1061.     dc.l    11025                    ; CD/4
  1062.     dc.l    12000                    ; DAT/4
  1063.     dc.l    14700                    ; CD/3
  1064.     dc.l    16000                    ; DAT/3
  1065.     dc.l    17640                    ; CD/2.5
  1066.     dc.l    18900
  1067.     dc.l    19200                    ; DAT/2.5
  1068.     dc.l    22050                    ; CD/2
  1069.     dc.l    24000                    ; DAT/2
  1070.     dc.l    27429
  1071. FREQUENCIES_OCS        EQU    (*-freqlist)>>2
  1072.     dc.l    29400                    ; CD/1.5
  1073.     dc.l    32000                    ; DAT/1.5
  1074.     dc.l    33075
  1075.     dc.l    37800
  1076.     dc.l    44100                    ; CD
  1077.     dc.l    48000                    ; DAT
  1078. FREQUENCIES        EQU    (*-freqlist)>>2
  1079.     dc.l    -1
  1080.  
  1081. * _CreateTable directly stolen from Christian Buchner's CyberSound
  1082. * audio sub system (with permission).
  1083.  
  1084. * _CreateTable **************************************************************
  1085.  
  1086.         ; Parameters
  1087.  
  1088.         ; a0 = Table address
  1089.         ; (MUST have enough space for 65536 UWORDS)
  1090.         ; a1 = Additive Array
  1091.         ; 256 UBYTEs
  1092.         ;
  1093.         ; the table is organized as follows:
  1094.         ; 32768 UWORDS positive range, ascending order
  1095.         ; 32768 UWORDS negative range, ascending order
  1096.         ; access: (a0,d0.l*2)
  1097.         ; where d0.w is signed word sample data
  1098.         ; and the upper word of d0.l is *cleared!*
  1099.  
  1100.  
  1101. _CreateTable    movem.l    a2/d2-d6,-(sp)
  1102.  
  1103.         lea    128(a1),a2
  1104.  
  1105.         move.l    a2,a1            ; count the number of steps
  1106.         moveq    #128-1,d0        ; in the positive range
  1107.         moveq    #0,d5
  1108. .countpositive    move.b    (a1)+,d1
  1109.         ext.w    d1
  1110.         ext.l    d1
  1111.         add.l    d1,d5
  1112.         dbra    d0,.countpositive    ; d5=number of steps
  1113.         move.l    #32768,d6        ; reset stretch counter
  1114.  
  1115.         move.l    a2,a1            ; middle value in calibdata
  1116.         move.w    #32768-1,d0        ; number of positive values -1
  1117.         moveq    #0,d1            ; HI value
  1118.         moveq    #0,d2            ; LO value
  1119.         moveq    #0,d3            ; counter
  1120. .fetchnext2    move.b    (a1)+,d4        ; add calibtable to counter
  1121.         ext.w    d4
  1122.         add.w    d4,d3
  1123. .outerloop2    tst.w    d3
  1124.         bgt.s    .positive2
  1125. .negative2    addq.w    #1,d1            ; increment HI value
  1126.         sub.w    d4,d2            ; reset LO value
  1127.         bra.s    .fetchnext2
  1128. .positive2    move.b    d1,(a0)+        ; store HI and LO value
  1129.         move.b    d2,(a0)+
  1130.         sub.l    d5,d6            ; stretch the table
  1131.         bpl.s    .repeat2        ; to 32768 entries
  1132.         add.l    #32768,d6
  1133.         addq.w    #1,d2            ; increment LO value
  1134.         subq.w    #1,d3            ; decrement counter
  1135. .repeat2    dbra    d0,.outerloop2
  1136.  
  1137.         move.l    a2,a1            ; count the number of steps
  1138.         moveq    #128-1,d0        ; in the negative range
  1139.         moveq    #0,d5
  1140. .countnegative    move.b    -(a1),d1
  1141.         ext.w    d1
  1142.         ext.l    d1
  1143.         add.l    d1,d5
  1144.         dbra    d0,.countnegative    ; d5=number of steps
  1145.         move.l    #32768,d6        ; reset stretch counter
  1146.  
  1147.         add.l    #2*32768,a0        ; place at the end of the table
  1148.         move.l    a2,a1            ; middle value in calibdata
  1149.         move.w    #32768-1,d0        ; number of negative values -1
  1150.         moveq    #-1,d1            ; HI value
  1151.         moveq    #-1,d2            ; LO value
  1152.         moveq    #0,d3            ; counter
  1153. .fetchnext1    move.b    -(a1),d4        ; add calibtable to counter
  1154.         ext.w    d4
  1155.         add.w    d4,d3
  1156.         add.w    d4,d2            ; maximize LO value
  1157. .outerloop1    tst.w    d3
  1158.         bgt.s    .positive1
  1159. .negative1    subq.w    #1,d1
  1160.         bra.s    .fetchnext1
  1161. .positive1    move.b    d2,-(a0)        ; store LO and HI value
  1162.         move.b    d1,-(a0)
  1163.         sub.l    d5,d6            ; stretch the table
  1164.         bpl.s    .repeat1        ; to 32768 entries
  1165.         add.l    #32768,d6
  1166.         subq.w    #1,d2            ; decrement lo value
  1167.         subq.w    #1,d3            ; decrement counter
  1168. .repeat1    dbra    d0,.outerloop1
  1169.  
  1170.         movem.l    (sp)+,a2/d2-d6
  1171.         rts
  1172.  
  1173.  
  1174. ****** [driver].audio/AHIsub_FreeAudio **************************************
  1175. *
  1176. *   NAME
  1177. *       AHIsub_FreeAudio -- Deallocates the audio hardware.
  1178. *
  1179. *   SYNOPSIS
  1180. *       AHIsub_FreeAudio( audioctrl );
  1181. *                         A2
  1182. *
  1183. *       void AHIsub_FreeAudio( struct AHIAudioCtrlDrv * );
  1184. *
  1185. *   IMPLEMENTATION
  1186. *       Deallocate the audio hardware and other resources allocated in
  1187. *       AHIsub_AllocAudio(). AHIsub_Stop() will always be called by
  1188. *       'ahi.device' before this call is made.
  1189. *
  1190. *   INPUTS
  1191. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1192. *
  1193. *   NOTES
  1194. *       It must be safe to call this routine even if AHIsub_AllocAudio()
  1195. *       was never called, failed or called more than once.
  1196. *
  1197. *   SEE ALSO
  1198. *       AHIsub_AllocAudio()
  1199. *
  1200. *****************************************************************************
  1201. *
  1202. *
  1203.  
  1204. AHIsub_FreeAudio:
  1205.     pushm    d2-d7/a2-a6
  1206.  
  1207.     move.l    a6,a5
  1208.     move.l    pb_SysLib(a5),a6
  1209.  
  1210.     move.l    ahiac_DriverData(a2),d0
  1211.     beq    .nopaula
  1212.     move.l    d0,a3
  1213.  
  1214.     move.l    p_CalibrationTable(a3),d0
  1215.     beq.b    .notable
  1216.     move.l    d0,a1
  1217.     call    FreeVec
  1218. .notable
  1219.     tst.l    p_audiodev(a3)
  1220.     bne.b    .noaudiodev
  1221.     move.l    p_audioreq(a3),a1
  1222.     move.w    #CMD_RESET,IO_COMMAND(a1)    ;Restore audio interrupts
  1223.     bsr.w    BeginIO
  1224.     move.l    p_audioport(a3),a0
  1225.     call    WaitPort
  1226.     move.l    p_audioport(a3),a0
  1227.     call    GetMsg
  1228.     move.l    p_audioreq(a3),a1
  1229.     subq.l    #1,p_audiodev(a3)
  1230.     call    CloseDevice
  1231. .noaudiodev
  1232.     move.l    p_audioreq(a3),d0
  1233.     beq.b    .noaudioreq
  1234.     move.l    d0,a1
  1235.     call    FreeVec
  1236. .noaudioreq
  1237.     move.l    p_audioport(a3),d0
  1238.     beq.b    .noaudioport
  1239.     move.l    d0,a0
  1240.     call    DeleteMsgPort
  1241. .noaudioport
  1242.     tst.l    p_AuraAddress(a3)
  1243.     beq    .noaura
  1244.     move.l    pb_CardResource(a5),d0
  1245.     beq    .noaura
  1246.     move.l    d0,a6
  1247.     move.l    p_CardHandle(a3),d0
  1248.     beq    .noaura
  1249.     move.l    d0,a1
  1250.     call    EndCardAccess
  1251.     move.l    p_CardHandle(a3),a1
  1252.     moveq    #CARDF_REMOVEHANDLE,d0
  1253.     call    ReleaseCard
  1254. .noaura
  1255.     move.l    pb_SysLib(a5),a6
  1256.     move.l    p_CardHandle(a3),d0
  1257.     beq    .nocardhandle
  1258.     move.l    d0,a1
  1259.     call    FreeVec
  1260. .nocardhandle
  1261.     move.l    pb_MiscResource(a5),a6
  1262.     tst.l    p_ParPortUser(a3)
  1263.     bne.b    .noparport
  1264.     moveq    #MR_PARALLELPORT,d0
  1265.     jsr    MR_FREEMISCRESOURCE(a6)
  1266. .noparport
  1267.     tst.l    p_ParBitsUser(a3)
  1268.     bne.b    .noparbits
  1269.     moveq    #MR_PARALLELBITS,d0
  1270.     jsr    MR_FREEMISCRESOURCE(a6)
  1271. .noparbits
  1272.     tst.l    p_SerBitsUser(a3)
  1273.     bne.b    .noserbits
  1274.     moveq    #MR_SERIALBITS,d0
  1275.     jsr    MR_FREEMISCRESOURCE(a6)
  1276. .noserbits
  1277.     move.l    pb_SysLib(a5),a6
  1278.     move.l    a3,a1
  1279.     clr.l    ahiac_DriverData(a2)
  1280.     call    FreeVec
  1281. .nopaula
  1282.     moveq    #0,d0
  1283.     popm    d2-d7/a2-a6
  1284.     rts
  1285.  
  1286.  
  1287. ****** [driver].audio/AHIsub_Disable ****************************************
  1288. *
  1289. *   NAME
  1290. *       AHIsub_Disable -- Temporary turn off audio interrupt/task
  1291. *
  1292. *   SYNOPSIS
  1293. *       AHIsub_Disable( audioctrl );
  1294. *                       A2
  1295. *
  1296. *       void AHIsub_Disable( struct AHIAudioCtrlDrv * );
  1297. *
  1298. *   IMPLEMENTATION
  1299. *       If you are lazy, then call exec.library/Disable().
  1300. *       If you are smart, only disable your own interrupt or task.
  1301. *
  1302. *   INPUTS
  1303. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1304. *
  1305. *   NOTES
  1306. *       This call should be guaranteed to preserve all registers.
  1307. *       This call nests.
  1308. *
  1309. *   SEE ALSO
  1310. *       AHIsub_Enable(), exec.library/Disable()
  1311. *
  1312. *****************************************************************************
  1313. *
  1314. *
  1315.  
  1316. AHIsub_Disable:
  1317.     push    a3
  1318.     move.l    ahiac_DriverData(a2),a3
  1319.     addq.w    #1,p_DisableCount(a3)
  1320.     move.w    #INTF_AUD0,custom+INTENA
  1321.     pop    a3
  1322.     rts
  1323.  
  1324. ****** [driver].audio/AHIsub_Enable *****************************************
  1325. *
  1326. *   NAME
  1327. *       AHIsub_Enable -- Turn on audio interrupt/task
  1328. *
  1329. *   SYNOPSIS
  1330. *       AHIsub_Enable( audioctrl );
  1331. *                      A2
  1332. *
  1333. *       void AHIsub_Enable( struct AHIAudioCtrlDrv * );
  1334. *
  1335. *   IMPLEMENTATION
  1336. *       If you are lazy, then call exec.library/Enable().
  1337. *       If you are smart, only enable your own interrupt or task.
  1338. *
  1339. *   INPUTS
  1340. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1341. *
  1342. *   NOTES
  1343. *       This call should be guaranteed to preserve all registers.
  1344. *       This call nests.
  1345. *
  1346. *   SEE ALSO
  1347. *       AHIsub_Disable(), exec.library/Enable()
  1348. *
  1349. *****************************************************************************
  1350. *
  1351. *
  1352.  
  1353. AHIsub_Enable:
  1354.     push    a3
  1355.     move.l    ahiac_DriverData(a2),a3
  1356.     subq.w    #1,p_DisableCount(a3)
  1357.     bne.b    .exit
  1358.     move.w    #INTF_SETCLR|INTF_AUD0,custom+INTENA
  1359. .exit
  1360.     pop    a3
  1361.     rts
  1362.  
  1363. ****** [driver].audio/AHIsub_Start ******************************************
  1364. *
  1365. *   NAME
  1366. *       AHIsub_Start -- Starts playback or recording
  1367. *
  1368. *   SYNOPSIS
  1369. *       error = AHIsub_Start( flags, audioctrl );
  1370. *       D0                    D0     A2
  1371. *
  1372. *       ULONG AHIsub_Start(ULONG, struct AHIAudioCtrlDrv * );
  1373. *
  1374. *   IMPLEMENTATION
  1375. *       What to do depends what you returned in AHIsub_AllocAudio().
  1376. *
  1377. *     * First, assume bit AHISB_PLAY in flags is set. This means that you
  1378. *       should begin playback.
  1379. *
  1380. *     - AHIsub_AllocAudio() returned AHISF_MIXING|AHISF_TIMING:
  1381. *
  1382. *       A) Allocate a mixing buffer of ahiac_BuffSize bytes. The buffer must
  1383. *          be long aligned!
  1384. *       B) Create/start an interrupt or task that will do 1-6 over and over
  1385. *          again until AHIsub_Stop() is called. Note that it is not a good
  1386. *          idea to do the actual mixing and conversion in a real hardware
  1387. *          interrupt. Signal a task or create a Software Interrupt to do
  1388. *          the number crunching.
  1389. *
  1390. *       1) Call the user Hook ahiac_PlayerFunc with the following parameters:
  1391. *                  A0 - (struct Hook *)
  1392. *                  A2 - (struct AHIAudioCtrlDrv *)
  1393. *                  A1 - Set to NULL.
  1394. *
  1395. *       2) [Call the ahiac_PreTimer function. If it returns TRUE (Z will be
  1396. *          cleared so you don't have to test d0), skip step 3 and 4. This
  1397. *          is used to avoid overloading the CPU. This step is optional.
  1398. *          A2 is assumed to point to struct AHIAudioCtrlDrv. All registers
  1399. *          except d0 are preserved.  (V4)]
  1400. *
  1401. *       3) Call the mixing Hook (ahiac_MixerFunc) with the following
  1402. *          parameters:
  1403. *                  A0 - (struct Hook *)           - The Hook itself
  1404. *                  A2 - (struct AHIAudioCtrlDrv *)
  1405. *                  A1 - (WORD *[])                - The mixing buffer.
  1406. *          Note that ahiac_MixerFunc preserves ALL registers.
  1407. *          The user Hook ahiac_SoundFunc will be called by the mixing
  1408. *          routine when a sample have been processed, so you don't have to
  1409. *          worry about that.
  1410. *          How the buffer will be filled is indicated by ahiac_Flags.
  1411. *          It is always filled with signed 16-bit (32 bit if AHIACB_HIFI in
  1412. *          in ahiac_Flags is set) words, even if playback is 8 bit. If
  1413. *          AHIDBB_STEREO is set (in ahiac_Flags), data for left and right
  1414. *          channel are interleaved:
  1415. *           1st sample left channel,
  1416. *           1st sample right channel,
  1417. *           2nd sample left channel,
  1418. *           ...,
  1419. *           ahiac_BuffSamples:th sample left channel,
  1420. *           ahiac_BuffSamples:th sample right channel.
  1421. *          If AHIDBB_STEREO is cleared, the mono data is stored:
  1422. *           1st sample,
  1423. *           2nd sample,
  1424. *           ...,
  1425. *           ahiac_BuffSamples:th sample.
  1426. *          Note that neither AHIACB_STEREO nor AHIACB_HIFI will be set if
  1427. *          you didn't report that you understand these flags when
  1428. *          AHI_AllocAudio() was called.
  1429. *
  1430. *          For AHI V2, the type of buffer is also available in ahiac_BuffType.
  1431. *          It is suggested that you use this value instead. ahiac_BuffType
  1432. *          can be one of AHIST_M16S, AHIST_S16S, AHIST_M32S and AHIST_S32S.
  1433. *
  1434. *       4) Convert the buffer if needed and feed it to the audio hardware.
  1435. *          Note that you may have to clear CPU caches if you are using DMA
  1436. *          to play the buffer, and the buffer is not allocated in non-
  1437. *          cachable RAM.
  1438. *
  1439. *       5) [Call the ahiac_PostTimer function. A2 is assumed to point to
  1440. *          struct AHIAudioCtrlDrv. All registers are preserved.  (V4)]
  1441. *
  1442. *       6) Wait until the whole buffer has been played, then repeat.
  1443. *
  1444. *       Use double buffering if possible!
  1445. *
  1446. *       You may DECREASE ahiac_BuffSamples slightly, for example to force an
  1447. *       even number of samples to be mixed. By doing this you will make
  1448. *       ahiac_PlayerFunc to be called at wrong frequency so be careful!
  1449. *       Even if ahiac_BuffSamples is defined ULONG, it will never be greater
  1450. *       than 65535.
  1451. *
  1452. *       ahiac_BuffSize is the largest size of the mixing buffer that will be
  1453. *       needed until AHIsub_Stop() is called.
  1454. *
  1455. *       ahiac_MaxBuffSamples is the maximum number of samples that will be
  1456. *       mixed (until AHIsub_Stop() is called). You can use this value if you
  1457. *       need to allocate DMA buffers.
  1458. *
  1459. *       ahiac_MinBuffSamples is the minimum number of samples that will be
  1460. *       mixed. Most drivers will ignore it.
  1461. *
  1462. *       If AHIsub_AllocAudio() returned with the AHISB_CANPOSTPROCESS bit set,
  1463. *       ahiac_BuffSize is large enough to hold two buffers. The mixing buffer
  1464. *       will be filled with the wet buffer first, immediately followed by the
  1465. *       dry buffer. I.e., ahiac_BuffSamples sample frames wet data, then
  1466. *       ahiac_BuffSamples sample frames dry data. The DSP fx should only be
  1467. *       applied to the wet buffer, and the two buffers should then be added
  1468. *       together. (V4)
  1469. *
  1470. *     - If AHIsub_AllocAudio() returned AHISF_MIXING, do as described above,
  1471. *       except calling ahiac_PlayerFunc. ahiac_PlayerFunc should be called
  1472. *       ahiac_PlayerFreq times per second, clocked by timers on your sound
  1473. *       card or by using 'realtime.library'. No other Amiga resources may
  1474. *       be used for timing (like direct CIA timers).
  1475. *       ahiac_MinBuffSamples and ahiac_MaxBuffSamples are undefined if
  1476. *       AHIsub_AllocAudio() returned AHISF_MIXING (AHISB_TIMING bit not set).
  1477. *
  1478. *     - If AHIsub_AllocAudio() returned with neither the AHISB_MIXING nor
  1479. *       the AHISB_TIMING bit set, then just start playback. Don't forget to
  1480. *       call ahiac_PlayerFunc ahiac_PlayerFreq times per second. Only your
  1481. *       own timing hardware or 'realtime.library' may be used. Note that
  1482. *       ahiac_MixerFunc, ahiac_BuffSamples, ahiac_MinBuffSamples,
  1483. *       ahiac_MaxBuffSamples and ahiac_BuffSize are undefined. ahiac_MixFreq
  1484. *       is the frequency the user wants to use for recording, if you support
  1485. *       that.
  1486. *
  1487. *     * Second, assume bit AHISB_RECORD in flags is set. This means that you
  1488. *       should start to sample. Create a interrupt or task that does the
  1489. *       following:
  1490. *
  1491. *       Allocate a buffer (you chose size, but try to keep it reasonable
  1492. *       small to avoid delays - it is suggested that RecordFunc is called
  1493. *       at least 4 times/second for the lowers sampling rate, and more often
  1494. *       for higher rates), and fill it with the sampled data. The buffer must
  1495. *       be long aligned, and it's size must be evenly divisible by four.
  1496. *       The format should always be AHIST_S16S (even with 8 bit mono samplers),
  1497. *       which means:
  1498. *           1st sample left channel,
  1499. *           1st sample right channel (same as prev. if mono),
  1500. *           2nd sample left channel,
  1501. *           ... etc.
  1502. *       Each sample is a signed word (WORD). The sample rate should be equal
  1503. *       to the mixing rate.
  1504. *
  1505. *       Call the ahiac_SamplerFunc Hook with the following parameters:
  1506. *           A0 - (struct Hook *)           - The Hook itself
  1507. *           A2 - (struct AHIAudioCtrlDrv *)
  1508. *           A1 - (struct AHIRecordMessage *)
  1509. *       The message should be filled as follows:
  1510. *           ahirm_Type - Set to AHIST_S16S.
  1511. *           ahirm_Buffer - A pointer to the filled buffer.
  1512. *           ahirm_Samples - How many sample frames stored.
  1513. *       You must not destroy the buffer until next time the Hook is called.
  1514. *
  1515. *       Repeat until AHIsub_Stop() is called.
  1516. *
  1517. *     * Note that both bits may be set when this function is called.
  1518. *
  1519. *   INPUTS
  1520. *       flags - See <libraries/ahi_sub.h>.
  1521. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1522. *
  1523. *   RESULT
  1524. *       Returns AHIE_OK if successful, else an error code as defined
  1525. *       in <devices/ahi.h>. AHIsub_Stop() will always be called, even
  1526. *       if this call failed.
  1527. *
  1528. *   NOTES
  1529. *       The driver must be able to handle multiple calls to this routine
  1530. *       without preceding calls to AHIsub_Stop().
  1531. *
  1532. *   SEE ALSO
  1533. *       AHIsub_Update(), AHIsub_Stop()
  1534. *
  1535. *****************************************************************************
  1536. *
  1537. *
  1538. *
  1539.  
  1540. AHIsub_Start:
  1541.     pushm    d2-d7/a2-a6
  1542.  
  1543.     move.l    d0,d7
  1544.     lea    custom,a4
  1545.     move.l    ahiac_DriverData(a2),a3
  1546.  
  1547.     btst    #AHISB_PLAY,d7
  1548.     beq    .dont_play
  1549.  
  1550. **
  1551. *** AHISB_PLAY
  1552. **
  1553.     moveq    #AHISF_PLAY,d0
  1554.     call    AHIsub_Stop            ;Stop current playback if any.
  1555.     call    AHIsub_Update            ;fill variables
  1556.  
  1557.     move.l    a6,a5
  1558.     move.l    pb_SysLib(a5),a6
  1559.  
  1560.     move.l    ahiac_BuffSize(a2),d0
  1561.     move.l    #MEMF_PUBLIC|MEMF_CLEAR,d1
  1562.     call    AllocVec
  1563.     move.l    d0,p_Mixbuffer(a3)
  1564.     beq    .error_nomem
  1565.  
  1566.     move.l    ahiac_MixFreq(a2),d1
  1567.     bsr.w    calcperiod
  1568.     move.w    d1,p_AudPer(a3)
  1569.  
  1570. * The init*bit?  routines allocates p_DMAbuffer, sets up
  1571. * p_AudPtr, sets the volume, stores the correct interrupt routines in
  1572. * p_PlayInt's and p_PlaySoftInt's IS_CODE.
  1573.  
  1574.     pea    .1(pc)
  1575.     move.b    p_Flags(a3),d0
  1576.     and.b    #PF_STEREO|PF_14BIT,d0
  1577.     beq.w    init8bitM
  1578.     cmp.b    #PF_STEREO,d0
  1579.     beq.w    init8bitS
  1580.     cmp.b    #PF_14BIT,d0
  1581.     beq.w    init14bitM
  1582.     bra.w    init14bitS
  1583. .1
  1584.     tst.l    d0
  1585.     bne    .exit
  1586.  
  1587. * Install play interrupt
  1588.     lea    p_PlayInt(a3),a1
  1589.     moveq    #INTB_AUD0,d0
  1590.     call    SetIntVector
  1591.     clr.w    p_DisableCount(a3)
  1592.  
  1593.     move.w    #INTF_SETCLR|INTF_AUD0,INTENA(a4)    ;enable
  1594.     move.w    #INTF_SETCLR|INTF_AUD0,INTREQ(a4)    ;start
  1595.  
  1596.     move.l    a5,a6
  1597.  
  1598.  
  1599. .dont_play
  1600.     btst    #AHISB_RECORD,d7
  1601.     beq    .dont_record
  1602. **
  1603. *** AHISB_RECORD
  1604. **
  1605.     btst    #PB_14BIT,p_Flags(a3)        ;Sanity check...
  1606.     bne    .error_unknown
  1607.  
  1608.     moveq    #AHISF_RECORD,d0
  1609.     call    AHIsub_Stop            ;Stop current recording if any.
  1610.  
  1611.     move.l    a6,a5
  1612.     move.l    pb_SysLib(a5),a6
  1613.  
  1614.     move.l    #RECORDSAMPLES*4,d0
  1615.     move.l    #MEMF_PUBLIC,d1
  1616.     call    AllocVec
  1617.     move.l    d0,p_RecBuffer1(a3)
  1618.     beq    .error_nomem
  1619.  
  1620.     move.l    d0,p_RecFillPtr(a3)
  1621.     move.w    #RECORDSAMPLES,p_RecFillCount(a3)
  1622.  
  1623.     move.l    #RECORDSAMPLES*4,d0
  1624.     move.l    #MEMF_PUBLIC,d1
  1625.     call    AllocVec
  1626.     move.l    d0,p_RecBuffer2(a3)
  1627.     beq    .error_nomem
  1628.  
  1629.     move.l    ahiac_MixFreq(a2),d1
  1630.     bsr.w    calcperiod
  1631.     lsr.w    #1,d1                ;Period/2 => Frequency·2
  1632.     move.w    d1,AUD2PER(a4)
  1633.     move.w    d1,AUD3PER(a4)
  1634.     move.w    p_MonitorVolume(a3),d0
  1635.     move.w    d0,AUD2VOL(a4)
  1636.     move.w    d0,AUD3VOL(a4)
  1637.  
  1638. * Install record interrupt
  1639.     move.w    p_Input(a3),d0
  1640.     beq    .parsampler
  1641.     cmp.w    #1,d0
  1642.     beq    .aurasampler
  1643.     cmp.w    #2,d0
  1644.     beq    .clarity
  1645.     bra    .error_unknown
  1646.  
  1647. .parsampler
  1648.     tst.b    p_Parallel(a3)            ;Parrallel port allocated?
  1649.     beq    .error_unknown
  1650.     lea    p_RecIntData(a3),a1
  1651.     move.l    a1,IS_DATA+p_RecInt(a3)
  1652.     move.l    #RecordInterrupt,IS_CODE+p_RecInt(a3)
  1653.  
  1654.     move.b    #$ff,_ciab+ciaddrb        ; Set parallel port to output
  1655.  
  1656.     bra    .setrecint
  1657.  
  1658. .clarity
  1659.     tst.b    p_Parallel(a3)            ;Parrallel port allocated?
  1660.     beq    .error_unknown
  1661.  
  1662.     move.l    pb_MiscResource(a5),a6
  1663.     move.l    #MR_SERIALBITS,d0    ; allocate serial port control lines
  1664.     lea    IDString(pc),a1
  1665.     jsr    MR_ALLOCMISCRESOURCE(a6)
  1666.     move.l    d0,p_SerBitsUser(a3)
  1667.     bne    .error_unknown
  1668.  
  1669.     lea    p_RecIntData(a3),a1
  1670.     move.l    a1,IS_DATA+p_RecInt(a3)
  1671.     move.l    #RecordInterruptClarity,IS_CODE+p_RecInt(a3)
  1672.  
  1673.     ; Set DTR, PRTBUSY and PRTRPOUT to outputs
  1674.     or.b    #CIAF_COMDTR!CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciaddra
  1675.     move.b    #$ff,_ciab+ciaddrb        ; Set parallel port to output
  1676.     ; Reset Clarity
  1677.     move.b    #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
  1678.     move.b    #CIAF_PRTRPOUT,_ciab+ciapra
  1679.     move.b    #CIAF_PRTRBUSY!CIAF_PRTRPOUT,_ciab+ciapra
  1680.     ; Clarity is now in stereo record mode
  1681.  
  1682.     bra    .setrecint
  1683.  
  1684. .aurasampler
  1685.     tst.l    p_AuraAddress(a3)        ;Aura sampler allocated?
  1686.     beq    .error_unknown
  1687.     lea    p_RecIntDataAura(a3),a1
  1688.     move.l    a1,IS_DATA+p_RecInt(a3)
  1689.     move.l    #RecordInterruptAura,IS_CODE+p_RecInt(a3)
  1690.     bra    .setrecint
  1691.  
  1692. .setrecint
  1693.     move.l    pb_SysLib(a5),a6
  1694.     lea    p_RecInt(a3),a1
  1695.     moveq    #INTB_AUD3,d0
  1696.     call    SetIntVector
  1697.  
  1698.     move.w    #DMAF_AUD2|DMAF_AUD3,DMACON(a4)        ;disable DMA
  1699.     move.w    #INTF_SETCLR|INTF_AUD3,INTENA(a4)    ;enable
  1700.     move.w    #INTF_SETCLR|INTF_AUD3,INTREQ(a4)    ;start
  1701.  
  1702. .dont_record
  1703. .return
  1704.     moveq    #AHIE_OK,d0
  1705. .exit
  1706.     popm    d2-d7/a2-a6
  1707.     rts
  1708. .error_nomem
  1709.     moveq    #AHIE_NOMEM,d0
  1710.     bra.b    .exit
  1711. .error_unknown
  1712.     moveq    #AHIE_UNKNOWN,d0
  1713.     bra.b    .exit
  1714.  
  1715.  
  1716. ;in:
  1717. * a2    AudioCtrl
  1718. * a3    paula
  1719. * a4    custom
  1720. * a5    paulaBase
  1721. * a6    ExecBase
  1722. init8bitM:
  1723.     PRINTF    2,"init8bitM()"
  1724.     move.l    #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
  1725.     move.l    #SoftInt_8bitM,IS_CODE+p_PlaySoftInt(a3)
  1726.     move.b    p_Flags(a3),d0
  1727.     btst    #PB_HIFI,d0
  1728.     beq    .nohifi
  1729.     move.l    #SoftInt_8bitMH,IS_CODE+p_PlaySoftInt(a3)
  1730. .nohifi
  1731.  
  1732.     move.l    p_MinBufferLength(a3),d0
  1733.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 8 bit samples
  1734.     addq.l    #3,d0
  1735.     and.b    #~3,d0                ;make it a multiple of 4
  1736.     move.l    d0,d2                ;d2 = channel size
  1737.  
  1738.     lsl.l    #1,d0                ;Double buffer
  1739.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1740.     call    AllocVec
  1741.     move.l    d0,p_DMAbuffer(a3)
  1742.     beq    .nomem
  1743.  
  1744.     move.l    d0,p_AudPtr1A(a3)
  1745.     move.l    d0,p_AudPtr2A(a3)
  1746.     add.l    d2,d0
  1747.     move.l    d0,p_AudPtr1B(a3)
  1748.     move.l    d0,p_AudPtr2B(a3)
  1749.  
  1750. ;    move.w    #64,AUD0VOL(a4)
  1751. ;    move.w    #64,AUD1VOL(a4)
  1752.  
  1753.     moveq    #0,d0
  1754.     rts
  1755. .nomem
  1756.     moveq    #AHIE_NOMEM,d0
  1757.     rts
  1758.  
  1759. ;in:
  1760. * a2    AudioCtrl
  1761. * a3    paula
  1762. * a5    paulaBase
  1763. * a6    ExecBase
  1764. init8bitS:
  1765.     PRINTF    2,"init8bitS()"
  1766.     move.l    #AudioInterrupt2,IS_CODE+p_PlayInt(a3)
  1767.     move.l    #SoftInt_8bitS,IS_CODE+p_PlaySoftInt(a3)
  1768.     move.b    p_Flags(a3),d0
  1769.     btst    #PB_HIFI,d0
  1770.     beq    .nohifi
  1771.     move.l    #SoftInt_8bitSH,IS_CODE+p_PlaySoftInt(a3)
  1772. .nohifi
  1773.  
  1774.     move.l    p_MinBufferLength(a3),d0
  1775.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 8 bit samples
  1776.     addq.l    #3,d0
  1777.     and.b    #~3,d0                ;make it a multiple of 4
  1778.     move.l    d0,d2                ;d2 = channel size
  1779.  
  1780.     lsl.l    #2,d0                ;Double buffer + Stereo
  1781.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1782.     call    AllocVec
  1783.     move.l    d0,p_DMAbuffer(a3)
  1784.     beq    .nomem
  1785.  
  1786.     move.l    d0,p_AudPtr1A(a3)
  1787.     add.l    d2,d0
  1788.     move.l    d0,p_AudPtr2A(a3)
  1789.     add.l    d2,d0
  1790.     move.l    d0,p_AudPtr1B(a3)
  1791.     add.l    d2,d0
  1792.     move.l    d0,p_AudPtr2B(a3)
  1793.  
  1794. ;    move.w    #64,AUD0VOL(a4)
  1795. ;    move.w    #64,AUD1VOL(a4)
  1796.  
  1797.     moveq    #0,d0
  1798.     rts
  1799. .nomem
  1800.     moveq    #AHIE_NOMEM,d0
  1801.     rts
  1802.  
  1803. ;in:
  1804. * a2    AudioCtrl
  1805. * a3    paula
  1806. * a5    paulaBase
  1807. * a6    ExecBase
  1808. init14bitM:
  1809.     PRINTF    2,"init14bitM()"
  1810.     move.l    #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
  1811.     lea    SoftInt_14bitM(pc),a0
  1812.     move.b    p_Flags(a3),d0
  1813.     btst    #PB_HIFI,d0
  1814.     beq    .nohifi1
  1815.     lea    SoftInt_14bitMH(pc),a0
  1816. .nohifi1
  1817.     tst.l    p_CalibrationTable(a3)
  1818.     beq.b    .nocalib
  1819.     lea    SoftInt_14CbitM(pc),a0
  1820.     move.b    p_Flags(a3),d0
  1821.     btst    #PB_HIFI,d0
  1822.     beq    .nohifi2
  1823.     lea    SoftInt_14CbitMH(pc),a0
  1824. .nohifi2
  1825. .nocalib
  1826.     move.l    a0,IS_CODE+p_PlaySoftInt(a3)
  1827.  
  1828.     move.l    p_MinBufferLength(a3),d0
  1829.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 16 bit samples
  1830.     addq.l    #3,d0
  1831.     and.b    #~3,d0                ;make it a multiple of 4
  1832.     move.l    d0,d2                ;d2 = channel size
  1833.  
  1834.     lsl.l    #2,d0                ;Double buffer + 2×8 bit
  1835.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1836.     call    AllocVec
  1837.     move.l    d0,p_DMAbuffer(a3)
  1838.     beq    .nomem
  1839.  
  1840.     move.l    d0,p_AudPtr1A(a3)
  1841.     move.l    d0,p_AudPtr2A(a3)
  1842.     add.l    d2,d0
  1843.     move.l    d0,p_AudPtr4A(a3)
  1844.     move.l    d0,p_AudPtr3A(a3)
  1845.     add.l    d2,d0
  1846.     move.l    d0,p_AudPtr1B(a3)
  1847.     move.l    d0,p_AudPtr2B(a3)
  1848.     add.l    d2,d0
  1849.     move.l    d0,p_AudPtr4B(a3)
  1850.     move.l    d0,p_AudPtr3B(a3)
  1851.  
  1852. ;    move.w    #64,AUD0VOL(a4)
  1853. ;    move.w    #64,AUD1VOL(a4)
  1854. ;    move.w    #1,AUD2VOL(a4)
  1855. ;    move.w    #1,AUD3VOL(a4)
  1856.  
  1857.     moveq    #0,d0
  1858.     rts
  1859. .nomem
  1860.     moveq    #AHIE_NOMEM,d0
  1861.     rts
  1862.  
  1863. ;in:
  1864. * a2    AudioCtrl
  1865. * a3    paula
  1866. * a5    paulaBase
  1867. * a6    ExecBase
  1868. init14bitS:
  1869.     PRINTF    2,"init14bitS()"
  1870.     move.l    #AudioInterrupt4,IS_CODE+p_PlayInt(a3)
  1871.     lea    SoftInt_14bitS(pc),a0
  1872.     move.b    p_Flags(a3),d0
  1873.     btst    #PB_HIFI,d0
  1874.     beq    .nohifi1
  1875.     lea    SoftInt_14bitSH(pc),a0
  1876. .nohifi1
  1877.     tst.l    p_CalibrationTable(a3)
  1878.     beq.b    .nocalib
  1879.     lea    SoftInt_14CbitS(pc),a0
  1880.     move.b    p_Flags(a3),d0
  1881.     btst    #PB_HIFI,d0
  1882.     beq    .nohifi2
  1883.     lea    SoftInt_14CbitSH(pc),a0
  1884. .nohifi2
  1885. .nocalib
  1886.     move.l    a0,IS_CODE+p_PlaySoftInt(a3)
  1887.  
  1888.     move.l    p_MinBufferLength(a3),d0
  1889.     add.l    ahiac_MaxBuffSamples(a2),d0    ;Max. # of 16 bit samples
  1890.     addq.l    #3,d0
  1891.     and.b    #~3,d0                ;make it a multiple of 4
  1892.     move.l    d0,d2                ;d2 = channel size
  1893.  
  1894.     lsl.l    #3,d0                ;Double buffer + 2×8 bit + Stereo
  1895.     move.l    #MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR,d1
  1896.     call    AllocVec
  1897.     move.l    d0,p_DMAbuffer(a3)
  1898.     beq    .nomem
  1899.  
  1900.     move.l    d0,p_AudPtr1A(a3)
  1901.     add.l    d2,d0
  1902.     move.l    d0,p_AudPtr2A(a3)
  1903.     add.l    d2,d0
  1904.     move.l    d0,p_AudPtr3A(a3)
  1905.     add.l    d2,d0
  1906.     move.l    d0,p_AudPtr4A(a3)
  1907.     add.l    d2,d0
  1908.     move.l    d0,p_AudPtr1B(a3)
  1909.     add.l    d2,d0
  1910.     move.l    d0,p_AudPtr2B(a3)
  1911.     add.l    d2,d0
  1912.     move.l    d0,p_AudPtr3B(a3)
  1913.     add.l    d2,d0
  1914.     move.l    d0,p_AudPtr4B(a3)
  1915.  
  1916. ;    move.w    #64,AUD0VOL(a4)
  1917. ;    move.w    #64,AUD1VOL(a4)
  1918. ;    move.w    #1,AUD2VOL(a4)
  1919. ;    move.w    #1,AUD3VOL(a4)
  1920.  
  1921.     moveq    #0,d0
  1922.     rts
  1923. .nomem
  1924.     moveq    #AHIE_NOMEM,d0
  1925.     rts
  1926.  
  1927. ****** [driver].audio/AHIsub_Update *****************************************
  1928. *
  1929. *   NAME
  1930. *       AHIsub_Update -- Update some variables
  1931. *
  1932. *   SYNOPSIS
  1933. *       AHIsub_Update( flags, audioctrl );
  1934. *                      D0     A2
  1935. *
  1936. *       void AHIsub_Update(ULONG, struct AHIAudioCtrlDrv * );
  1937. *
  1938. *   IMPLEMENTATION
  1939. *       All you have to do is to update some variables:
  1940. *       Mixing & timing: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc,
  1941. *       ahiac_BuffSamples (and perhaps ahiac_PlayerFreq if you use it).
  1942. *       Mixing only: ahiac_PlayerFunc, ahiac_MixerFunc, ahiac_SamplerFunc and
  1943. *           ahiac_PlayerFreq.
  1944. *       Nothing: ahiac_PlayerFunc, ahiac_SamplerFunc and ahiac_PlayerFreq.
  1945. *
  1946. *   INPUTS
  1947. *       flags - Currently no flags defined.
  1948. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  1949. *
  1950. *   RESULT
  1951. *
  1952. *   NOTES
  1953. *       This call must be safe from interrupts.
  1954. *
  1955. *   SEE ALSO
  1956. *       AHIsub_Start()
  1957. *
  1958. *****************************************************************************
  1959. *
  1960. *
  1961. *
  1962.  
  1963. AHIsub_Update:
  1964.     pushm    d2-d7/a2-a6
  1965.  
  1966.     call    AHIsub_Disable        ;make sure we don't get an interrupt
  1967.                     ;while updating our local variables
  1968.     move.l    ahiac_DriverData(a2),a3
  1969.  
  1970.     move.l    ahiac_PlayerFunc(a2),a0
  1971.     move.l    a0,p_PlayerHook(a3)
  1972.     move.l    h_Entry(a0),p_PlayerEntry(a3)
  1973.  
  1974.     move.l    ahiac_BuffSamples(a2),d1
  1975.     and.b    #~3,d1            ;make it a multiple of 4
  1976.     move.l    d1,ahiac_BuffSamples(a2)
  1977.     move.l    d1,d0
  1978.     lsr.l    #2,d0
  1979.     subq.l    #1,d0
  1980.     move.l    d0,p_LoopTimes(a3)    ;See softints. (Unrolled)
  1981.  
  1982.     PRINTF    2,"LoopTimes: %ld", d0
  1983.  
  1984. ;    move.l    p_MinBufferLength(a3),d0
  1985. ;    divu.w    d1,d0
  1986. ;    ext.l    d0
  1987. ;    move.l    d0,p_RepeatTimes(a3)    ;that's really times-1 (dbf dx,label)
  1988.  
  1989. ;    PRINTF    2,"RepeatTimes: %ld", d0
  1990.  
  1991. ;    addq.l    #1,d0
  1992. ;    mulu.w    d1,d0
  1993. ;    lsr.l    #1,d0            ;length in words
  1994. ;    move.w    d0,p_AudLen(a3)
  1995.  
  1996. ;    PRINTF    2,"AudLen: %ld", d0
  1997.  
  1998.     move.l    ahiac_MixerFunc(a2),a0
  1999.     move.l    a0,p_MixHook(a3)
  2000.     move.l    h_Entry(a0),p_MixEntry(a3)
  2001.  
  2002.     call    AHIsub_Enable
  2003.     moveq    #0,d0
  2004.     popm    d2-d7/a2-a6
  2005.     rts
  2006.  
  2007.  
  2008. ****** [driver].audio/AHIsub_Stop *******************************************
  2009. *
  2010. *   NAME
  2011. *       AHIsub_Stop -- Stops playback.
  2012. *
  2013. *   SYNOPSIS
  2014. *       AHIsub_Stop( flags, audioctrl );
  2015. *                    D0     A2
  2016. *
  2017. *       void AHIsub_Stop( ULONG, struct AHIAudioCtrlDrv * );
  2018. *
  2019. *   IMPLEMENTATION
  2020. *       Stop playback and/or recording, remove all resources allocated by
  2021. *       AHIsub_Start().
  2022. *
  2023. *   INPUTS
  2024. *       flags - See <libraries/ahi_sub.h>.
  2025. *       audioctrl - pointer to an AHIAudioCtrlDrv structure.
  2026. *
  2027. *   NOTES
  2028. *       It must be safe to call this routine even if AHIsub_Start() was never
  2029. *       called, failed or called more than once.
  2030. *
  2031. *   SEE ALSO
  2032. *       AHIsub_Start()
  2033. *
  2034. *****************************************************************************
  2035. *
  2036. *
  2037.  
  2038. AHIsub_Stop:
  2039.     pushm    d2-d7/a2-a6
  2040.  
  2041.     lea    custom,a4
  2042.     move.l    a6,a5
  2043.     move.l    pb_SysLib(a5),a6
  2044.     move.l    ahiac_DriverData(a2),a3
  2045.  
  2046.     push    d0
  2047.     btst    #AHISB_PLAY,d0
  2048.     beq    .dontplay
  2049.  
  2050. **
  2051. *** AHISB_PLAY
  2052. **
  2053.     move.w    #DMAF_AUDIO,DMACON(a4)        ;disable audio DMA
  2054.  
  2055.     move.w    #INTF_AUD0,INTENA(a4)
  2056.     move.w    #INTF_AUD0,INTREQ(a4)        ;Clear any waiting interrupts
  2057.     move.l    #Interrupt_Dummy,IS_CODE+p_PlayInt(a3)
  2058.     lea    p_PlayInt(a3),a1
  2059.     moveq    #INTB_AUD0,d0
  2060.     call    SetIntVector
  2061.  
  2062.     moveq    #0,d0
  2063.     move.w    d0,AUD0VOL(a4)
  2064.     move.w    d0,AUD1VOL(a4)
  2065.     move.w    d0,AUD2VOL(a4)
  2066.     move.w    d0,AUD3VOL(a4)
  2067.  
  2068.     move.l    p_DMAbuffer(a3),d0
  2069.     beq.b    .nodmamem
  2070.     move.l    d0,a1
  2071.     clr.l    p_DMAbuffer(a3)
  2072.     call    FreeVec
  2073. .nodmamem
  2074.     move.l    p_Mixbuffer(a3),d0
  2075.     beq.b    .nomixmem
  2076.     move.l    d0,a1
  2077.     clr.l    p_Mixbuffer(a3)
  2078.     call    FreeVec
  2079. .nomixmem
  2080.  
  2081. .dontplay
  2082.     pop    d0
  2083.     btst    #AHISB_RECORD,d0
  2084.     beq    .dontrecord
  2085.  
  2086. **
  2087. *** AHISB_RECORD
  2088. **
  2089.     btst    #PB_14BIT,p_Flags(a3)        ;Sanity check...
  2090.     bne    .dontrecord
  2091.  
  2092.     move.w    #INTF_AUD3,INTENA(a4)
  2093.     move.w    #INTF_AUD3,INTREQ(a4)        ;Clear any waiting interrupts
  2094.  
  2095.     move.l    #Interrupt_Dummy,IS_CODE+p_RecInt(a3)
  2096.     lea    p_RecInt(a3),a1
  2097.     moveq    #INTB_AUD3,d0
  2098.     call    SetIntVector
  2099.  
  2100.     move.w    #0,AUD2VOL(a4)
  2101.     move.w    #0,AUD3VOL(a4)
  2102.  
  2103.     move.l    p_RecBuffer1(a3),d0
  2104.     beq.b    .norecmem1
  2105.     move.l    d0,a1
  2106.     clr.l    p_RecBuffer1(a3)
  2107.     call    FreeVec
  2108. .norecmem1
  2109.     move.l    p_RecBuffer2(a3),d0
  2110.     beq.b    .norecmem2
  2111.     move.l    d0,a1
  2112.     clr.l    p_RecBuffer2(a3)
  2113.     call    FreeVec
  2114. .norecmem2
  2115. .dontrecord
  2116. .return
  2117.     moveq    #0,d0
  2118.     popm    d2-d7/a2-a6
  2119.     rts
  2120.  
  2121. ****** [driver].audio/AHIsub_#? *********************************************
  2122. *
  2123. *   NAME
  2124. *       AHIsub_SetEffect -- Set effect.
  2125. *       AHIsub_SetFreq -- Set frequency.
  2126. *       AHIsub_SetSound -- Set sound.
  2127. *       AHIsub_SetVol -- Set volume and stereo panning.
  2128. *       AHIsub_LoadSound -- Prepare a sound for playback.
  2129. *       AHIsub_UnloadSound -- Discard a sound.
  2130. *
  2131. *   SYNOPSIS
  2132. *       See functions in 'ahi.device'.
  2133. *
  2134. *   IMPLEMENTATION
  2135. *       If AHIsub_AllocAudio() did not return with bit AHISB_MIXING set,
  2136. *       all user calls to these function will be routed to the driver.
  2137. *
  2138. *       If AHIsub_AllocAudio() did return with bit AHISB_MIXING set, the
  2139. *       calls will first be routed to the driver, and only handled by
  2140. *       'ahi.device' if the driver returned AHIS_UNKNOWN. This way it is
  2141. *       possible to add effects that the sound card handles on its own, like
  2142. *       filter and echo effects.
  2143. *
  2144. *       For what each function does, see the autodocs for 'ahi.device'.
  2145. *
  2146. *   INPUTS
  2147. *       See functions in 'ahi.device'.
  2148. *
  2149. *   NOTES
  2150. *       See functions in 'ahi.device'.
  2151. *
  2152. *   SEE ALSO
  2153. *       ahi.device/AHI_SetEffect(), ahi.device/AHI_SetFreq(),
  2154. *       ahi.device/AHI_SetSound(), ahi.device/AHI_SetVol(),
  2155. *       ahi.device/AHI_LoadSound(), ahi.device/AHI_UnloadSound()
  2156. *       
  2157. *
  2158. *****************************************************************************
  2159. *
  2160. *
  2161.  
  2162. AHIsub_SetVol:
  2163. AHIsub_SetFreq:
  2164. AHIsub_SetSound:
  2165. AHIsub_SetEffect:
  2166. AHIsub_LoadSound:
  2167. AHIsub_UnloadSound:
  2168.     moveq    #AHIS_UNKNOWN,d0
  2169.     rts
  2170.  
  2171. ****** [driver].audio/AHIsub_GetAttr ****************************************
  2172. *
  2173. *   NAME
  2174. *       AHIsub_GetAttr -- Returns information about audio modes or driver
  2175. *
  2176. *   SYNOPSIS
  2177. *       AHIsub_GetAttr( attribute, argument, default, taglist, audioctrl );
  2178. *       D0              D0         D1        D2       A1       A2
  2179. *
  2180. *       LONG AHIsub_GetAttr( ULONG, LONG, LONG, struct TagItem *,
  2181. *                            struct AHIAudioCtrlDrv * );
  2182. *
  2183. *   IMPLEMENTATION
  2184. *       Return the attribute based on a tag list and an AHIAudioCtrlDrv
  2185. *       structure, which are the same that will be passed to
  2186. *       AHIsub_AllocAudio() by 'ahi.device'. If the attribute is
  2187. *       unknown to you, return the default.
  2188. *
  2189. *   INPUTS
  2190. *       attribute - Is really a Tag and can be one of the following:
  2191. *           AHIDB_Bits - Return how many output bits the tag list will
  2192. *               result in.
  2193. *           AHIDB_MaxChannels - Return the resulting number of channels.
  2194. *           AHIDB_Frequencies - Return how many mixing/sampling frequencies
  2195. *               you support
  2196. *           AHIDB_Frequency - Return the argument:th frequency
  2197. *               Example: You support 3 frequencies 32, 44.1 and 48 kHz.
  2198. *                   If argument is 1, return 44100.
  2199. *           AHIDB_Index - Return the index which gives the frequency closest
  2200. *               to argument.
  2201. *               Example: You support 3 frequencies 32, 44.1 and 48 kHz.
  2202. *                   If argument is 40000, return 1 (=> 44100).
  2203. *           AHIDB_Author - Return pointer to name of driver author:
  2204. *               "Martin 'Leviticus' Blom"
  2205. *           AHIDB_Copyright - Return pointer to copyright notice, including
  2206. *               the '©' character: "© 1996 Martin Blom" or "Public Domain"
  2207. *           AHIDB_Version - Return pointer version string, normal Amiga
  2208. *               format: "paula 1.5 (18.2.96)\r\n"
  2209. *           AHIDB_Annotation - Return pointer to an annotation string, which
  2210. *               can be several lines.
  2211. *           AHIDB_Record - Are you a sampler, too? Return TRUE or FALSE.
  2212. *           AHIDB_FullDuplex - Return TRUE or FALSE.
  2213. *           AHIDB_Realtime - Return TRUE or FALSE.
  2214. *           AHIDB_MaxPlaySamples - Normally, return the default. See
  2215. *               AHIsub_AllocAudio(), section 2.
  2216. *           AHIDB_MaxRecordSamples - Return the size of the buffer you fill
  2217. *               when recording.
  2218. *
  2219. *           The following are associated with AHIsub_HardwareControl() and are
  2220. *           new for V2.
  2221. *           AHIDB_MinMonitorVolume
  2222. *           AHIDB_MaxMonitorVolume - Return the lower/upper limit for
  2223. *               AHIC_MonitorVolume. If unsupported but always 1.0, return
  2224. *               1.0 for both.
  2225. *           AHIDB_MinInputGain
  2226. *           AHIDB_MaxInputGain - Return the lower/upper limit for
  2227. *               AHIC_InputGain. If unsupported but always 1.0, return 1.0 for
  2228. *               both.
  2229. *           AHIDB_MinOutputVolume
  2230. *           AHIDB_MaxOutputVolume - Return the lower/upper limit for
  2231. *               AHIC_OutputVolume.
  2232. *           AHIDB_Inputs - Return how many inputs you have.
  2233. *           AHIDB_Input - Return a short string describing the argument:th
  2234. *               input. Number 0 should be the default one. Example strings
  2235. *               can be "Line 1", "Mic", "Optical" or whatever.
  2236. *           AHIDB_Outputs - Return how many outputs you have.
  2237. *           AHIDB_Output - Return a short string describing the argument:th
  2238. *               output. Number 0 should be the default one. Example strings
  2239. *               can be "Line 1", "Headphone", "Optical" or whatever.
  2240. *       argument - extra info for some attributes.
  2241. *       default - What you should return for unknown attributes.
  2242. *       taglist - Pointer to a tag list that eventually will be fed to
  2243. *           AHIsub_AllocAudio(), or NULL.
  2244. *       audioctrl - Pointer to an AHIAudioCtrlDrv structure that eventually
  2245. *           will be fed to AHIsub_AllocAudio(), or NULL.
  2246. *
  2247. *   NOTES
  2248. *
  2249. *   SEE ALSO
  2250. *       AHIsub_AllocAudio(), AHIsub_HardwareControl(),
  2251. *       ahi.device/AHI_GetAudioAttrsA()
  2252. *
  2253. *****************************************************************************
  2254. *
  2255. *
  2256.  
  2257. AHIsub_GetAttr:
  2258.     pushm    d2-d7/a2-a6
  2259.     move.l    a6,a5
  2260.     move.l    pb_UtilLib(a5),a6
  2261.  
  2262.  
  2263.     pushm    d0-d1
  2264.     moveq    #FALSE,d3
  2265.     move.l    a1,a0
  2266.     move.l    a1,d0
  2267.     beq    .notaglist
  2268.     move.l    #AHIDB_Paula14Bit,d0
  2269.     move.l    d3,d1
  2270.     call    GetTagData
  2271.     move.l    d0,d3
  2272. .notaglist
  2273.     popm    d0-d1
  2274.  
  2275.     and.l    #~(AHI_TagBaseR),d0
  2276.     cmp.l    #AHIDB_Data & ~(AHI_TagBaseR),d0
  2277.     bhi    .default
  2278.     sub.w    #100,d0
  2279.     lsl.w    #1,d0
  2280.     move.w    .jt(pc,d0.w),d0
  2281.     beq    .default
  2282.     jsr    .jt(pc,d0.w)
  2283.  
  2284. .exit
  2285.     popm    d2-d7/a2-a6
  2286.     rts
  2287.  
  2288. .default
  2289.     move.l    d2,d0
  2290.     bra    .exit
  2291.  
  2292. .jt
  2293.     dc.w    0                ; AHIDB_AudioID
  2294.     dc.w    0                ; AHIDB_Driver
  2295.     dc.w    0                ; AHIDB_Flags
  2296.     dc.w    0                ; AHIDB_Volume
  2297.     dc.w    0                ; AHIDB_Panning
  2298.     dc.w    0                ; AHIDB_Stereo
  2299.     dc.w    0                ; AHIDB_HiFi
  2300.     dc.w    0                ; AHIDB_PingPong
  2301.     dc.w    0                ; AHIDB_MultTable
  2302.     dc.w    0                ; AHIDB_Name
  2303.     dc.w    ga_Bits-.jt            ; AHIDB_Bits
  2304.     dc.w    0                ; AHIDB_MaxChannels
  2305.     dc.w    0                ; AHIDB_MinMixFreq
  2306.     dc.w    0                ; AHIDB_MaxMixFreq
  2307.     dc.w    ga_Record-.jt            ; AHIDB_Record
  2308.     dc.w    ga_Frequencies-.jt        ; AHIDB_Frequencies
  2309.     dc.w    0                ; AHIDB_FrequencyArg
  2310.     dc.w    ga_Frequency-.jt        ; AHIDB_Frequency
  2311.     dc.w    ga_Author-.jt            ; AHIDB_Author
  2312.     dc.w    ga_Copyright-.jt        ; AHIDB_Copyright
  2313.     dc.w    ga_Version-.jt            ; AHIDB_Version
  2314.     dc.w    ga_Annotation-.jt        ; AHIDB_Annotation
  2315.     dc.w    0                ; AHIDB_BufferLen
  2316.     dc.w    0                ; AHIDB_IndexArg
  2317.     dc.w    ga_Index-.jt            ; AHIDB_Index
  2318.     dc.w    ga_Realtime-.jt            ; AHIDB_Realtime
  2319.     dc.w    0                ; AHIDB_MaxPlaySamples
  2320.     dc.w    ga_MaxRecordSamples-.jt        ; AHIDB_MaxRecordSample
  2321.     dc.w    0                ; 
  2322.     dc.w    ga_FullDuplex-.jt        ; AHIDB_FullDuplex
  2323.     dc.w    ga_MinMonitorVolume-.jt        ; AHIDB_MinMonitorVolum
  2324.     dc.w    ga_MaxMonitorVolume-.jt        ; AHIDB_MaxMonitorVolum
  2325.     dc.w    ga_MinInputGain-.jt        ; AHIDB_MinInputGain
  2326.     dc.w    ga_MaxInputGain-.jt        ; AHIDB_MaxInputGain
  2327.     dc.w    ga_MinOutputVolume-.jt        ; AHIDB_MinOutputVolume
  2328.     dc.w    ga_MaxOutputVolume-.jt        ; AHIDB_MaxOutputVolume
  2329.     dc.w    ga_Inputs-.jt            ; AHIDB_Inputs
  2330.     dc.w    0                ; AHIDB_InputArg
  2331.     dc.w    ga_Input-.jt            ; AHIDB_Input
  2332.     dc.w    ga_Outputs-.jt            ; AHIDB_Outputs
  2333.     dc.w    0                ; AHIDB_OutputArg
  2334.     dc.w    ga_Output-.jt            ; AHIDB_Output
  2335.     dc.w    0                ; AHIDB_Data
  2336.  
  2337. ga_Bits:
  2338.     moveq    #14,d0
  2339.     tst.l    d3
  2340.     bne    .exit
  2341.     moveq    #8,d0
  2342. .exit
  2343.     rts
  2344.  
  2345. ga_Record:
  2346.     moveq    #FALSE,d0
  2347.     tst.l    d3
  2348.     bne    .exit
  2349.     moveq    #TRUE,d0
  2350. .exit
  2351.     rts
  2352.  
  2353. ga_Frequencies:
  2354.     bsr    checkvideo
  2355.     tst.l    d0
  2356.     beq    .1
  2357.     moveq    #FREQUENCIES,d0
  2358.     rts
  2359. .1
  2360.     moveq    #FREQUENCIES_OCS,d0
  2361.     rts
  2362.  
  2363. ga_Frequency:
  2364.     lsl.w    #2,d1
  2365.     lea    freqlist(pc),a0
  2366. ;    move.l    (a0,d1.w),d1
  2367. ;    bsr    calcperiod
  2368.     move.l    (a0,d1.w),d0
  2369.     rts
  2370.  
  2371. ga_Author:
  2372.     lea    .author(pc),a0
  2373.     move.l    a0,d0
  2374.     rts
  2375. .author        dc.b    "Martin 'Leviticus' Blom",0
  2376.     even
  2377.  
  2378. ga_Copyright:
  2379.     lea    .copyright(pc),a0
  2380.     move.l    a0,d0
  2381.     rts
  2382. .copyright    dc.b    "Public Domain",0
  2383.     even
  2384.  
  2385. ga_Version:
  2386.     lea    IDString(pc),a0
  2387.     move.l    a0,d0
  2388.     rts
  2389.  
  2390. ga_Annotation:
  2391.     lea    .anno(pc),a0
  2392.     move.l    a0,d0
  2393.     rts
  2394. .anno        dc.b    "14 bit routines by Christian Buchner.",0
  2395.     even
  2396.  
  2397. ga_Index:
  2398.     move.l    d1,d0
  2399.     bsr    findfreq
  2400.     move.l    d1,d0
  2401.     rts
  2402.  
  2403.  
  2404. ga_Realtime:
  2405.     moveq    #TRUE,d0
  2406.     rts
  2407.  
  2408. ga_MaxRecordSamples:
  2409.     move.l    #RECORDSAMPLES,d0
  2410.     rts
  2411.  
  2412. ga_FullDuplex:
  2413.     moveq    #FALSE,d0
  2414.     tst.l    d3
  2415.     bne    .exit
  2416.     moveq    #TRUE,d0
  2417. .exit
  2418.     rts
  2419.  
  2420.  
  2421. ga_MinMonitorVolume:
  2422.     moveq    #0,d0
  2423.     rts
  2424.  
  2425. ga_MaxMonitorVolume:
  2426.     moveq    #0,d0
  2427.     tst.l    d3
  2428.     bne    .exit
  2429.     move.l    #$10000,d0
  2430. .exit
  2431.     rts
  2432.  
  2433. ga_MinInputGain:
  2434.     move.l    #$10000,d0
  2435.     rts
  2436.  
  2437. ga_MaxInputGain:
  2438.     move.l    #$10000,d0
  2439.     rts
  2440.  
  2441. ga_MinOutputVolume:
  2442.     move.l    #$10000,d0
  2443.     tst.l    d3
  2444.     bne    .exit
  2445.     moveq    #0,d0
  2446. .exit
  2447.     rts
  2448.  
  2449. ga_MaxOutputVolume:
  2450.     move.l    #$10000,d0
  2451.     rts
  2452.  
  2453.  
  2454. ga_Inputs:
  2455.     moveq    #0,d0
  2456.     tst.l    d3
  2457.     bne    .exit
  2458.     moveq    #3,d0
  2459. .exit
  2460.     rts
  2461.  
  2462. ga_Input:
  2463.     lsl.l    #2,d1
  2464.     move.l    .inputs(pc,d1.w),d0
  2465.     rts
  2466. .inputs        dc.l    .input0
  2467.         dc.l    .input1
  2468.         dc.l    .input2
  2469.  
  2470. .input0        dc.b    "Parallel port sampler",0
  2471. .input1        dc.b    "Aura sampler",0
  2472. .input2        dc.b    "Clarity sampler",0
  2473.     even
  2474.  
  2475. ga_Outputs:
  2476.     moveq    #1,d0
  2477.     rts
  2478.  
  2479. ga_Output:
  2480.     lea    .output(pc),a0
  2481.     move.l    a0,d0
  2482.     rts
  2483. .output        dc.b    "Line",0
  2484.     even
  2485.  
  2486.  
  2487. ****** [driver].audio/AHIsub_HardwareControl ********************************
  2488. *
  2489. *   NAME
  2490. *       AHIsub_HardwareControl -- Modify sound card settings
  2491. *
  2492. *   SYNOPSIS
  2493. *       AHIsub_HardwareControl( attribute,  argument, audioctrl );
  2494. *       D0                      D0          D1        A2
  2495. *
  2496. *       LONG AHIsub_HardwareControl( ULONG, LONG, struct AHIAudioCtrlDrv * );
  2497. *
  2498. *   IMPLEMENTATION
  2499. *       Set or return the state of a particular hardware component. AHI uses
  2500. *       AHIsub_GetAttr() to supply the user with limits and what tags are
  2501. *       available.
  2502. *
  2503. *   INPUTS
  2504. *       attribute - Is really a Tag and can be one of the following:
  2505. *           AHIC_MonitorVolume - Set the input monitor volume to argument.
  2506. *           AHIC_MonitorVolume_Query - Return the current input monitor
  2507. *               volume (argument is ignored).
  2508. *
  2509. *           AHIC_InputGain - Set the input gain to argument. (V2)
  2510. *           AHIC_InputGain_Query (V2)
  2511. *
  2512. *           AHIC_OutputVolume - Set the output volume to argument. (V2)
  2513. *           AHIC_OutputVolume_Query (V2)
  2514. *
  2515. *           AHIC_Input - Use the argument:th input source (default is 0). (V2)
  2516. *           AHIC_Input_Query (V2)
  2517. *
  2518. *           AHIC_Output - Use the argument:th output destination (default
  2519. *               is 0). (V2)
  2520. *           AHIC_Output_Query (V2)
  2521. *
  2522. *       argument - What value attribute should be set to.
  2523. *       audioctrl - Pointer to an AHIAudioCtrlDrv structure.
  2524. *
  2525. *   RESULT
  2526. *       Return the state of selected attribute. If you were asked to set
  2527. *       something, return TRUE. If attribute is unknown to you or unsupported,
  2528. *       return FALSE.
  2529. *
  2530. *   NOTES
  2531. *       This call must be safe from interrupts.
  2532. *
  2533. *   SEE ALSO
  2534. *       ahi.device/AHI_ControlAudioA(), AHIsub_GetAttr()
  2535. *
  2536. *****************************************************************************
  2537. *
  2538. *
  2539.  
  2540. AHIsub_HardwareControl:
  2541.     cmp.l    #AHIC_MonitorVolume,d0
  2542.     bne.b    .dontsetmonvol
  2543.     move.l    ahiac_DriverData(a2),a1
  2544.     lsr.l    #8,d1
  2545.     lsr.l    #2,d1
  2546.     move.w    d1,p_MonitorVolume(a1)
  2547.     bra.b    .exit
  2548. .dontsetmonvol
  2549.     cmp.l    #AHIC_MonitorVolume_Query,d0
  2550.     bne.b    .dontgetmonvol
  2551.     move.l    ahiac_DriverData(a2),a1
  2552.     moveq    #0,d0
  2553.     move.w    p_MonitorVolume(a1),d0
  2554.     lsl.l    #8,d0
  2555.     lsl.l    #2,d0
  2556.     bra.b    .quit
  2557. .dontgetmonvol
  2558.     cmp.l    #AHIC_OutputVolume,d0
  2559.     bne.b    .dontsetoutvol
  2560.     move.l    ahiac_DriverData(a2),a1
  2561.     lsr.l    #8,d1
  2562.     lsr.l    #2,d1
  2563.     move.w    d1,p_OutputVolume(a1)
  2564.     bra.b    .exit
  2565. .dontsetoutvol
  2566.     cmp.l    #AHIC_OutputVolume_Query,d0
  2567.     bne.b    .dontgetoutvol
  2568.     move.l    ahiac_DriverData(a2),a1
  2569.     moveq    #0,d0
  2570.     move.w    p_OutputVolume(a1),d0
  2571.     lsl.l    #8,d0
  2572.     lsl.l    #2,d0
  2573.     bra.b    .quit
  2574. .dontgetoutvol
  2575.     cmp.l    #AHIC_Input,d0
  2576.     bne.b    .dontsetinput
  2577.     move.l    ahiac_DriverData(a2),a1
  2578.     move.w    d1,p_Input(a1)
  2579.     bra.b    .exit
  2580. .dontsetinput
  2581.     cmp.l    #AHIC_Input_Query,d0
  2582.     bne.b    .dontgetinput
  2583.     move.l    ahiac_DriverData(a2),a1
  2584.     moveq    #0,d0
  2585.     move.w    p_Input(a1),d0
  2586.     bra.b    .quit
  2587. .dontgetinput
  2588.     moveq    #FALSE,d0
  2589. .quit
  2590.     rts
  2591. .exit
  2592.     moveq    #TRUE,d0
  2593.     rts
  2594.  
  2595.  
  2596.  
  2597.  
  2598.  
  2599.  
  2600.  
  2601. *******************************************************************************
  2602. *******************************************************************************
  2603.  
  2604. Interrupt_Dummy:
  2605.     move.w    #INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3,INTREQ(a0)
  2606. SoftInt_Dummy:
  2607.     rts
  2608.  
  2609. *******************************************************************************
  2610. *******************************************************************************
  2611.  
  2612. ;in:
  2613. * d0    scratch
  2614. * d1    INTENAR & INTREQR
  2615. * a0    custom
  2616. * a1    &(paula->p_RecIntData)
  2617. * a5    &RecordInterrupt
  2618. * a6    ExecBase
  2619. RecordInterrupt:
  2620.  
  2621. * This function will be executed up to 28000 times per second - that's once per
  2622. * rasterline! It has to be as fast as possible.
  2623.  
  2624.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  2625.     moveq    #0,d0
  2626.     move.b    _ciaa+ciaprb,d0            ;read parallel port
  2627.  IFGE    __CPU-68020
  2628.     move.l    convtable(pc,d0.w*4),d0        ;1 unsigned byte -> 2 signed words
  2629.  ELSE
  2630.     add.w    d0,d0
  2631.     add.w    d0,d0
  2632.     move.l    convtable(pc,d0.w),d0
  2633.  ENDC
  2634.     move.w    d0,AUD2DAT(a0)            ;left
  2635.     move.w    d0,AUD3DAT(a0)            ;right
  2636.  
  2637.     move.l    (a1),a5                ;p_RecFillPtr
  2638.     move.l    d0,(a5)+            ;store sample in buffer
  2639.     move.l    a5,(a1)+            ;update pointer
  2640.     subq.w    #1,(a1)                ;p_ReqFillCount
  2641.     beq    ri_Filled            ;branch if buffer filled
  2642.     rts
  2643.  
  2644. convtable
  2645. CNT    SET    0
  2646.     REPT    256
  2647.     dc.b    CNT-128,CNT-128,CNT-128,CNT-128
  2648. CNT    SET    CNT+1
  2649.     ENDR
  2650.  
  2651. ;in:
  2652. * d0    scratch
  2653. * d1    INTENAR & INTREQR
  2654. * a0    custom
  2655. * a1    &(paula->p_RecIntData)
  2656. * a5    &RecordInterrupt
  2657. * a6    ExecBase
  2658. RecordInterruptClarity:
  2659.  
  2660. * This function will be executed up to 28000 times per second - that's once per
  2661. * rasterline! It has to be as fast as possible.
  2662.  
  2663.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  2664.  
  2665.     lea    _ciab+ciatahi,a5
  2666.  
  2667.     move.b    _ciaa+ciaprb,d0            ;left lsb
  2668.     ror.l    #8,d0                ;d0: L0xxxxxx
  2669.     tst.b    (a5)                ;3x700 kHz wait states
  2670.     tst.b    (a5)
  2671.     tst.b    (a5)
  2672.  
  2673.     move.b    _ciaa+ciaprb,d0            ;left msb
  2674.     ror.l    #8,d0                ;d0: L1L0xxxx
  2675.     tst.b    (a5)                ;3x700 kHz wait states
  2676.     tst.b    (a5)
  2677.     tst.b    (a5)
  2678.  
  2679.     move.b    _ciaa+ciaprb,d0            ;right lsb
  2680.     lsl.w    #8,d0                ;d0: L1L0R0xx
  2681.     tst.b    (a5)                ;3x700 kHz wait states
  2682.     tst.b    (a5)
  2683.     tst.b    (a5)
  2684.  
  2685.     move.b    _ciaa+ciaprb,d0            ;right msb
  2686.     ror.w    #8,d0                ;d0: L1L0R1R0
  2687.  
  2688.     move.l    (a1),a5                ;p_RecFillPtr
  2689.     move.l    d0,(a5)+            ;store sample in buffer
  2690.     move.l    a5,(a1)+            ;update pointer
  2691.  
  2692.     move.w    d0,d1
  2693.     lsr.w    #8,d0
  2694.     move.b    d0,d1
  2695.  
  2696.     move.w    d1,AUD2DAT(a0)            ;right
  2697.     move.w    d1,AUD3DAT(a0)            ;left
  2698.  
  2699.     subq.w    #1,(a1)                ;p_ReqFillCount
  2700.     beq    ri_Filled            ;branch if buffer filled
  2701.     rts
  2702.  
  2703. ;in:
  2704. * d0    scratch
  2705. * d1    INTENAR & INTREQR
  2706. * a0    custom
  2707. * a1    &(paula->p_RecIntDataAura)
  2708. * a5    &RecordInterrupt
  2709. * a6    ExecBase
  2710. RecordInterruptAura:
  2711.  
  2712. * This function will be executed up to 28000 times per second - that's once per
  2713. * rasterline! It has to be as fast as possible.
  2714.  
  2715.     move.w    #INTF_AUD2|INTF_AUD3,INTREQ(a0)    ;Clear the interrupt flags
  2716.     move.l    (a1)+,a5
  2717.     move.l    (a5),d0                ;read aura sampler
  2718.     eor.l    #$80008000,d0
  2719.     move.l    (a1),a5                ;p_RecFillPtr
  2720.     move.l    d0,(a5)+            ;store sample in buffer
  2721.     move.l    a5,(a1)+            ;update pointer
  2722.  
  2723.     move.w    d0,d1
  2724.     lsr.w    #8,d0
  2725.     move.b    d0,d1
  2726.  
  2727.     move.w    d1,AUD2DAT(a0)            ;left
  2728.     move.w    d1,AUD3DAT(a0)            ;right
  2729.  
  2730.     subq.w    #1,(a1)                ;p_ReqFillCount
  2731.     beq    ri_Filled            ;branch if buffer filled
  2732.     rts
  2733.  
  2734. *******************************************************************************
  2735.  
  2736. ri_Filled:
  2737.  
  2738. * This part is only executed every RECORDSAMPLES:th time... No need to hurry.
  2739.  
  2740.     move.l    8(a1),d0            ;p_RecBuffer2->
  2741.     move.l    4(a1),8(a1)            ;p_RecBuffer1->p_RecBuffer2
  2742.     move.l    d0,4(a1)            ;            ->p_RecBuffer1
  2743.     move.l    d0,-4(a1)            ;p_RecFillPtr
  2744.     move.w    #RECORDSAMPLES,(a1)        ;p_ReqFillCount
  2745.     move.l    12(a1),a1            ;p_RecSoftIntPtr
  2746.     jmp    _LVOCause(a6)
  2747.  
  2748.  
  2749. ;in:
  2750. * d0    scratch
  2751. * d1    scratch
  2752. * a0    scratch
  2753. * a1    struct paula *
  2754. * a5    scratch
  2755. RecordSoftInt:
  2756.  
  2757. * This function is not executed many times per second and is therefore not
  2758. * fully optimized... ;)
  2759.     push    a2
  2760.     move.w    p_MonitorVolume(a1),d0
  2761.     move.w    d0,custom+AUD2VOL
  2762.     move.w    d0,custom+AUD3VOL
  2763.     move.l    p_RecBuffer2(a1),p_rmBuffer(a1)
  2764.     move.l    p_AudioCtrl(a1),a2
  2765.     lea    p_RecordMessage(a1),a1
  2766.     move.l    ahiac_SamplerFunc(a2),a0
  2767.     move.l    h_Entry(a0),a5
  2768.     jsr    (a5)
  2769.     pop    a2
  2770.     rts
  2771.  
  2772. *******************************************************************************
  2773. *******************************************************************************
  2774.  
  2775. ;in:
  2776. * d0    scratch
  2777. * d1    INTENAR & INTREQR
  2778. * a0    custom
  2779. * a1    struct paula *
  2780. * a5    &AudioInterrupt
  2781. * a6    ExecBase
  2782.  
  2783. AudioInterrupt2:                ;Two hardware channels used
  2784. ;    move.l    p_AudLenPer(a1),d0
  2785. ;    move.l    d0,AUD0LEN(a0)
  2786. ;    move.l    d0,AUD1LEN(a0)
  2787.     move.w    p_AudPer(a1),d0
  2788.     move.w    d0,AUD0PER(a0)
  2789.     move.w    d0,AUD1PER(a0)
  2790.     move.w    p_OutputVolume(a1),AUD0VOL(a0)
  2791.     move.w    p_OutputVolume(a1),AUD1VOL(a0)
  2792.  
  2793.     move.l    p_DoubleBufferOffset(a1),d0
  2794.     eor.w    #4*4,d0
  2795.     move.l    d0,p_DoubleBufferOffset(a1)
  2796.  
  2797.     lea    p_AudPtrs(a1,d0.l),a5
  2798.     tst.w    p_SwapChannels(a1)
  2799.     bne    .swap
  2800.     move.l    (a5)+,AUD0LC(a0)
  2801.     move.l    (a5)+,AUD1LC(a0)
  2802.     bra    .1
  2803. .swap
  2804.     move.l    (a5)+,AUD1LC(a0)
  2805.     move.l    (a5)+,AUD0LC(a0)
  2806. .1
  2807.     lea    p_PlaySoftInt(a1),a1
  2808.     move.w    #INTF_AUD0,INTREQ(a0)        ;Clear the interrupt 
  2809.     jmp    _LVOCause(a6)            ;start PlaySoftInt
  2810.  
  2811.  
  2812. AudioInterrupt4:                ;Four hardware channels used
  2813. ;    move.l    p_AudLenPer(a1),d0
  2814. ;    move.l    d0,AUD0LEN(a0)
  2815. ;    move.l    d0,AUD1LEN(a0)
  2816. ;    move.l    d0,AUD2LEN(a0)
  2817. ;    move.l    d0,AUD3LEN(a0)
  2818.     move.w    p_AudPer(a1),d0
  2819.     move.w    d0,AUD0PER(a0)
  2820.     move.w    d0,AUD1PER(a0)
  2821.     move.w    d0,AUD2PER(a0)
  2822.     move.w    d0,AUD3PER(a0)
  2823.     move.w    #64,AUD0VOL(a0)
  2824.     move.w    #64,AUD1VOL(a0)
  2825.     move.w    #1,AUD2VOL(a0)
  2826.     move.w    #1,AUD3VOL(a0)
  2827.  
  2828.     move.l    p_DoubleBufferOffset(a1),d0
  2829.     eor.w    #4*4,d0
  2830.     move.l    d0,p_DoubleBufferOffset(a1)
  2831.  
  2832.     lea    p_AudPtrs(a1,d0.l),a5
  2833.     tst.w    p_SwapChannels(a1)
  2834.     bne    .swap
  2835.     move.l    (a5)+,AUD0LC(a0)
  2836.     move.l    (a5)+,AUD1LC(a0)
  2837.     move.l    (a5)+,AUD2LC(a0)
  2838.     move.l    (a5)+,AUD3LC(a0)
  2839.     bra    .1
  2840. .swap
  2841.     move.l    (a5)+,AUD1LC(a0)
  2842.     move.l    (a5)+,AUD0LC(a0)
  2843.     move.l    (a5)+,AUD3LC(a0)
  2844.     move.l    (a5)+,AUD2LC(a0)
  2845. .1
  2846.     lea    p_PlaySoftInt(a1),a1
  2847.     move.w    #INTF_AUD0,INTREQ(a0)        ;Clear the interrupt 
  2848.     jmp    _LVOCause(a6)            ;start PlaySoftInt
  2849.  
  2850.  
  2851. *******************************************************************************
  2852.  
  2853. ;in:
  2854. * d0    scratch
  2855. * d1    scratch
  2856. * a0    scratch
  2857. * a1    struct paula *
  2858. * a5    scratch
  2859.  
  2860. CONVERT_PRE    MACRO
  2861.     pushm    std
  2862.     move.l    a1,a6
  2863.     move.l    p_AudioCtrl(a6),a2
  2864.     move.l    ahiac_PreTimer(a2),a0
  2865.     jsr    (a0)
  2866.     move.l    d0,d7
  2867.  
  2868.     move.l    p_DoubleBufferOffset(a6),d0
  2869.     lea    p_AudPtrs(a6,d0.l),a0
  2870.     movem.l    (a0)+,d2/d3/d4/d5        ;get all 4 buffer pointers
  2871.  
  2872.     moveq    #0,d6
  2873. .repeat
  2874.     movem.l    p_PlayerHookRegs(a6),a0/a1/a3
  2875.     jsr    (a3)                ;call Player Hook
  2876.     tst.l    d7
  2877.     bne    .skip
  2878.     movem.l    p_MixHookRegs(a6),a0/a1/a3
  2879.     jsr    (a3)                ;call Mixer Hook
  2880.     move.l    p_LoopTimes(a6),d0
  2881.     ENDM
  2882.  
  2883. ;
  2884. ; Conversion code here!
  2885. ;
  2886. ; d0    counter
  2887. ; d1    scratch
  2888. ; d2-d5    buffer pointers
  2889. ; d6    (sample counter/4)
  2890. ; d7    (pretimer flag)
  2891. ; a0    scratch
  2892. ; a1    source buffer
  2893. ; a2    AudioCtrl
  2894. ; a3-a5    scratch
  2895. ; a6    struct paula *
  2896. ;
  2897. ; Conversion code here!
  2898. ;
  2899.  
  2900. CONVERT_POST    MACRO
  2901. .skip
  2902.     add.l    ahiac_BuffSamples(a2),d6
  2903.     cmp.l    p_MinBufferLength(a6),d6
  2904.     blo    .repeat
  2905.     move.l    ahiac_PostTimer(a2),a0
  2906.     jsr    (a0)
  2907.     move.l    d6,d0
  2908.     lea    custom,a0
  2909.     popm    std
  2910.     ENDM
  2911.  
  2912. ; Exit code here
  2913. ; d0    Samples in buffer
  2914. ; a0    custom
  2915.  
  2916. *******************************************************************************
  2917.  
  2918. SoftInt_8bitM:
  2919.  
  2920.     CONVERT_PRE
  2921.  
  2922.     move.l    d2,a0                ;get buffer ptr
  2923. .loop
  2924.     move.b    (a1),d1
  2925.     lsl.l    #8,d1
  2926.     move.b    2(a1),d1
  2927.     lsl.l    #8,d1
  2928.     move.b    4(a1),d1
  2929.     lsl.l    #8,d1
  2930.     move.b    6(a1),d1
  2931.     move.l    d1,(a0)+
  2932.     addq.w    #8,a1
  2933.     dbf    d0,.loop
  2934.     move.l    a0,d2                ;save buffer ptr
  2935.  
  2936.     CONVERT_POST
  2937.  
  2938.     lsr.l    #1,d0
  2939.     move.w    d0,AUD0LEN(a0)
  2940.     move.w    d0,AUD1LEN(a0)
  2941.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  2942.     rts
  2943.  
  2944. *******************************************************************************
  2945.  
  2946. SoftInt_8bitMH:
  2947.     CONVERT_PRE
  2948.  
  2949.     move.l    d2,a0                ;get buffer ptr
  2950. .loop
  2951.     move.b    (a1),d1
  2952.     lsl.l    #8,d1
  2953.     move.b    4(a1),d1
  2954.     lsl.l    #8,d1
  2955.     move.b    8(a1),d1
  2956.     lsl.l    #8,d1
  2957.     move.b    12(a1),d1
  2958.     move.l    d1,(a0)+
  2959.     add.w    #16,a1
  2960.     dbf    d0,.loop
  2961.     move.l    a0,d2                ;save buffer ptr
  2962.  
  2963.     CONVERT_POST
  2964.  
  2965.     lsr.l    #1,d0
  2966.     move.w    d0,AUD0LEN(a0)
  2967.     move.w    d0,AUD1LEN(a0)
  2968.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  2969.     rts
  2970.  
  2971. *******************************************************************************
  2972.  
  2973. SoftInt_8bitS:
  2974.     CONVERT_PRE
  2975.  
  2976.     move.l    d2,a0                ;get buffer ptr
  2977.     move.l    d3,a3                ;get buffer ptr
  2978. .loop
  2979.  
  2980. ; Left
  2981.     move.b    (a1),d1
  2982.     lsl.l    #8,d1
  2983.     move.b    4(a1),d1
  2984.     lsl.l    #8,d1
  2985.     move.b    8(a1),d1
  2986.     lsl.l    #8,d1
  2987.     move.b    12(a1),d1
  2988.     move.l    d1,(a3)+
  2989.  
  2990. ; Right
  2991.     move.b    2(a1),d1
  2992.     lsl.l    #8,d1
  2993.     move.b    6(a1),d1
  2994.     lsl.l    #8,d1
  2995.     move.b    10(a1),d1
  2996.     lsl.l    #8,d1
  2997.     move.b    14(a1),d1
  2998.     move.l    d1,(a0)+
  2999.  
  3000.     add.w    #16,a1
  3001.     dbf    d0,.loop
  3002.     move.l    a0,d2                ;save buffer ptr
  3003.     move.l    a3,d3                ;save buffer ptr
  3004.  
  3005.     CONVERT_POST
  3006.  
  3007.     lsr.l    #1,d0
  3008.     move.w    d0,AUD0LEN(a0)
  3009.     move.w    d0,AUD1LEN(a0)
  3010.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3011.     rts
  3012.  
  3013. *******************************************************************************
  3014.  
  3015. SoftInt_8bitSH:
  3016.     CONVERT_PRE
  3017.  
  3018.     move.l    d2,a0                ;get buffer ptr
  3019.     move.l    d3,a3                ;get buffer ptr
  3020. .loop
  3021.  
  3022. ; Left
  3023.     move.b    (a1),d1
  3024.     lsl.l    #8,d1
  3025.     move.b    8(a1),d1
  3026.     lsl.l    #8,d1
  3027.     move.b    16(a1),d1
  3028.     lsl.l    #8,d1
  3029.     move.b    24(a1),d1
  3030.     move.l    d1,(a3)+
  3031.  
  3032. ; Right
  3033.     move.b    4(a1),d1
  3034.     lsl.l    #8,d1
  3035.     move.b    12(a1),d1
  3036.     lsl.l    #8,d1
  3037.     move.b    20(a1),d1
  3038.     lsl.l    #8,d1
  3039.     move.b    28(a1),d1
  3040.     move.l    d1,(a0)+
  3041.  
  3042.     add.w    #32,a1
  3043.     dbf    d0,.loop
  3044.     move.l    a0,d2                ;save buffer ptr
  3045.     move.l    a3,d3                ;save buffer ptr
  3046.  
  3047.     CONVERT_POST
  3048.  
  3049.     lsr.l    #1,d0
  3050.     move.w    d0,AUD0LEN(a0)
  3051.     move.w    d0,AUD1LEN(a0)
  3052.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1,DMACON(a0)
  3053.     rts
  3054.  
  3055. *******************************************************************************
  3056.  
  3057. SoftInt_14bitM:
  3058.     CONVERT_PRE
  3059.  
  3060.     move.l    d2,a0                ;get buffer ptr
  3061.     move.l    d5,a5                ;get buffer ptr
  3062. .loop
  3063.  
  3064. ; High
  3065.     move.b    (a1),d1
  3066.     lsl.l    #8,d1
  3067.     move.b    2(a1),d1
  3068.     lsl.l    #8,d1
  3069.     move.b    4(a1),d1
  3070.     lsl.l    #8,d1
  3071.     move.b    6(a1),d1
  3072.     move.l    d1,(a0)+
  3073.  
  3074. ; Low
  3075.     move.b    1(a1),d1
  3076.     lsr.b    #2,d1
  3077.     lsl.l    #8,d1
  3078.     move.b    3(a1),d1
  3079.     lsr.b    #2,d1
  3080.     lsl.l    #8,d1
  3081.     move.b    5(a1),d1
  3082.     lsr.b    #2,d1
  3083.     lsl.l    #8,d1
  3084.     move.b    7(a1),d1
  3085.     lsr.b    #2,d1
  3086.     move.l    d1,(a5)+
  3087.  
  3088.     addq.w    #8,a1
  3089.     dbf    d0,.loop
  3090.     move.l    a0,d2                ;save buffer ptr
  3091.     move.l    a5,d5                ;save buffer ptr
  3092.  
  3093.     CONVERT_POST
  3094.  
  3095.     lsr.l    #1,d0
  3096.     move.w    d0,AUD0LEN(a0)
  3097.     move.w    d0,AUD1LEN(a0)
  3098.     move.w    d0,AUD2LEN(a0)
  3099.     move.w    d0,AUD3LEN(a0)
  3100.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3101.     rts
  3102.  
  3103. *******************************************************************************
  3104.  
  3105.  
  3106. SoftInt_14bitMH:
  3107.     CONVERT_PRE
  3108.  
  3109.     move.l    d2,a0                ;get buffer ptr
  3110.     move.l    d5,a5                ;get buffer ptr
  3111. .loop
  3112.  
  3113. ; High
  3114.     move.b    (a1),d1
  3115.     lsl.l    #8,d1
  3116.     move.b    4(a1),d1
  3117.     lsl.l    #8,d1
  3118.     move.b    8(a1),d1
  3119.     lsl.l    #8,d1
  3120.     move.b    12(a1),d1
  3121.     move.l    d1,(a0)+
  3122.  
  3123. ; Low
  3124.     move.b    1(a1),d1
  3125.     lsr.b    #2,d1
  3126.     lsl.l    #8,d1
  3127.     move.b    5(a1),d1
  3128.     lsr.b    #2,d1
  3129.     lsl.l    #8,d1
  3130.     move.b    9(a1),d1
  3131.     lsr.b    #2,d1
  3132.     lsl.l    #8,d1
  3133.     move.b    13(a1),d1
  3134.     lsr.b    #2,d1
  3135.     move.l    d1,(a5)+
  3136.  
  3137.     add.w    #16,a1
  3138.     dbf    d0,.loop
  3139.     move.l    a0,d2                ;save buffer ptr
  3140.     move.l    a5,d5                ;save buffer ptr
  3141.  
  3142.     CONVERT_POST
  3143.  
  3144.     lsr.l    #1,d0
  3145.     move.w    d0,AUD0LEN(a0)
  3146.     move.w    d0,AUD1LEN(a0)
  3147.     move.w    d0,AUD2LEN(a0)
  3148.     move.w    d0,AUD3LEN(a0)
  3149.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3150.     rts
  3151.  
  3152. *******************************************************************************
  3153.  
  3154. SoftInt_14CbitM:
  3155.     CONVERT_PRE
  3156.  
  3157.     move.l    d2,a0                ;get buffer ptr
  3158.     move.l    d5,a5                ;get buffer ptr
  3159.     move.l    p_CalibrationTable(a6),a3
  3160.     moveq    #0,d3
  3161. .loop
  3162.  
  3163.  IFGE    __CPU-68020
  3164.     move.w    (a1)+,d3
  3165.     move.w    (a3,d3.l*2),d3
  3166.  ELSE
  3167.     moveq    #0,d3
  3168.     move.w    (a1)+,d3
  3169.      add.w    d3,d3
  3170.      move.w    (a3,d3.l),d3
  3171.  ENDC
  3172.     move.b    d3,d1
  3173.     lsl.l    #8,d1                ;xxxxAAxx
  3174.     move.w    d3,d2
  3175.     lsl.l    #8,d2                ;xxaaxxxx
  3176.  IFGE    __CPU-68020
  3177.     move.w    (a1)+,d3
  3178.     move.w    (a3,d3.l*2),d3
  3179.  ELSE
  3180.     moveq    #0,d3
  3181.     move.w    (a1)+,d3
  3182.      add.w    d3,d3
  3183.      move.w    (a3,d3.l),d3
  3184.  ENDC
  3185.     move.b    d3,d1
  3186.     lsl.l    #8,d1                ;xxAABBxx
  3187.     move.w    d3,d2
  3188.     lsl.l    #8,d2                ;aabbxxxx
  3189.  IFGE    __CPU-68020
  3190.     move.w    (a1)+,d3
  3191.     move.w    (a3,d3.l*2),d3
  3192.  ELSE
  3193.     moveq    #0,d3
  3194.     move.w    (a1)+,d3
  3195.      add.w    d3,d3
  3196.      move.w    (a3,d3.l),d3
  3197.  ENDC
  3198.     move.b    d3,d1
  3199.     lsl.l    #8,d1                ;AABBCCxx
  3200.     move.w    d3,d2                ;aabbccxx
  3201.  
  3202.  IFGE    __CPU-68020
  3203.     move.w    (a1)+,d3
  3204.     move.w    (a3,d3.l*2),d3
  3205.  ELSE
  3206.     moveq    #0,d3
  3207.     move.w    (a1)+,d3
  3208.      add.w    d3,d3
  3209.      move.w    (a3,d3.l),d3
  3210.  ENDC
  3211.     move.b    d3,d1                ;AABBCCDD
  3212.     lsr.w    #8,d3
  3213.     move.b    d3,d2                ;aabbccdd
  3214.  
  3215.     move.l    d1,(a5)+
  3216.     move.l    d2,(a0)+
  3217.  
  3218.     dbf    d0,.loop
  3219.     move.l    a0,d2                ;save buffer ptr
  3220.     move.l    a5,d5                ;save buffer ptr
  3221.  
  3222.     CONVERT_POST
  3223.  
  3224.     lsr.l    #1,d0
  3225.     move.w    d0,AUD0LEN(a0)
  3226.     move.w    d0,AUD1LEN(a0)
  3227.     move.w    d0,AUD2LEN(a0)
  3228.     move.w    d0,AUD3LEN(a0)
  3229.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3230.     rts
  3231.  
  3232. *******************************************************************************
  3233.  
  3234. SoftInt_14CbitMH:
  3235.     CONVERT_PRE
  3236.  
  3237.     move.l    d2,a0                ;get buffer ptr
  3238.     move.l    d5,a5                ;get buffer ptr
  3239.     move.l    p_CalibrationTable(a6),a3
  3240.     moveq    #0,d3
  3241. .loop
  3242.  
  3243.  IFGE    __CPU-68020
  3244.     move.w    (a1),d3
  3245.     move.w    (a3,d3.l*2),d3
  3246.  ELSE
  3247.     moveq    #0,d3
  3248.     move.w    (a1),d3
  3249.      add.w    d3,d3
  3250.      move.w    (a3,d3.l),d3
  3251.  ENDC
  3252.     move.b    d3,d1
  3253.     lsl.l    #8,d1                ;xxxxAAxx
  3254.     move.w    d3,d2
  3255.     lsl.l    #8,d2                ;xxaaxxxx
  3256.  IFGE    __CPU-68020
  3257.     move.w    4(a1),d3
  3258.     move.w    (a3,d3.l*2),d3
  3259.  ELSE
  3260.     moveq    #0,d3
  3261.     move.w    4(a1),d3
  3262.      add.w    d3,d3
  3263.      move.w    (a3,d3.l),d3
  3264.  ENDC
  3265.     move.b    d3,d1
  3266.     lsl.l    #8,d1                ;xxAABBxx
  3267.     move.w    d3,d2
  3268.     lsl.l    #8,d2                ;aabbxxxx
  3269.  IFGE    __CPU-68020
  3270.     move.w    8(a1),d3
  3271.     move.w    (a3,d3.l*2),d3
  3272.  ELSE
  3273.     moveq    #0,d3
  3274.     move.w    8(a1),d3
  3275.      add.w    d3,d3
  3276.      move.w    (a3,d3.l),d3
  3277.  ENDC
  3278.     move.b    d3,d1
  3279.     lsl.l    #8,d1                ;AABBCCxx
  3280.     move.w    d3,d2                ;aabbccxx
  3281.  
  3282.  IFGE    __CPU-68020
  3283.     move.w    12(a1),d3
  3284.     move.w    (a3,d3.l*2),d3
  3285.  ELSE
  3286.     moveq    #0,d3
  3287.     move.w    12(a1),d3
  3288.      add.w    d3,d3
  3289.      move.w    (a3,d3.l),d3
  3290.  ENDC
  3291.     move.b    d3,d1                ;AABBCCDD
  3292.     lsr.w    #8,d3
  3293.     move.b    d3,d2                ;aabbccdd
  3294.  
  3295.     move.l    d1,(a5)+
  3296.     add.w    #16,a1
  3297.     move.l    d2,(a0)+
  3298.  
  3299.     dbf    d0,.loop
  3300.     move.l    a0,d2                ;save buffer ptr
  3301.     move.l    a5,d5                ;save buffer ptr
  3302.  
  3303.     CONVERT_POST
  3304.  
  3305.     lsr.l    #1,d0
  3306.     move.w    d0,AUD0LEN(a0)
  3307.     move.w    d0,AUD1LEN(a0)
  3308.     move.w    d0,AUD2LEN(a0)
  3309.     move.w    d0,AUD3LEN(a0)
  3310.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3311.     rts
  3312.  
  3313.  
  3314. *******************************************************************************
  3315.  
  3316. SoftInt_14bitS:
  3317.     CONVERT_PRE
  3318.  
  3319.     move.l    d2,a0                ;get buffer ptr
  3320.     move.l    d3,a3                ;get buffer ptr
  3321.     move.l    d4,a4                ;get buffer ptr
  3322.     move.l    d5,a5                ;get buffer ptr
  3323. .loop
  3324.  
  3325. ; Left High
  3326.     move.b    (a1),d1
  3327.     lsl.l    #8,d1
  3328.     move.b    4(a1),d1
  3329.     lsl.l    #8,d1
  3330.     move.b    8(a1),d1
  3331.     lsl.l    #8,d1
  3332.     move.b    12(a1),d1
  3333.     move.l    d1,(a3)+
  3334.  
  3335. ; Left Low
  3336.     move.b    1(a1),d1
  3337.     lsr.b    #2,d1
  3338.     lsl.l    #8,d1
  3339.     move.b    5(a1),d1
  3340.     lsr.b    #2,d1
  3341.     lsl.l    #8,d1
  3342.     move.b    9(a1),d1
  3343.     lsr.b    #2,d1
  3344.     lsl.l    #8,d1
  3345.     move.b    13(a1),d1
  3346.     lsr.b    #2,d1
  3347.     move.l    d1,(a4)+
  3348.  
  3349. ; Right High
  3350.     move.b    2(a1),d1
  3351.     lsl.l    #8,d1
  3352.     move.b    6(a1),d1
  3353.     lsl.l    #8,d1
  3354.     move.b    10(a1),d1
  3355.     lsl.l    #8,d1
  3356.     move.b    14(a1),d1
  3357.     move.l    d1,(a0)+
  3358.  
  3359. ; Right Low
  3360.     move.b    3(a1),d1
  3361.     lsr.b    #2,d1
  3362.     lsl.l    #8,d1
  3363.     move.b    7(a1),d1
  3364.     lsr.b    #2,d1
  3365.     lsl.l    #8,d1
  3366.     move.b    11(a1),d1
  3367.     lsr.b    #2,d1
  3368.     lsl.l    #8,d1
  3369.     move.b    15(a1),d1
  3370.     lsr.b    #2,d1
  3371.     move.l    d1,(a5)+
  3372.  
  3373.     add.w    #16,a1
  3374.     dbf    d0,.loop
  3375.     move.l    a0,d2                ;save buffer ptr
  3376.     move.l    a3,d3                ;save buffer ptr
  3377.     move.l    a4,d4                ;save buffer ptr
  3378.     move.l    a5,d5                ;save buffer ptr
  3379.  
  3380.     CONVERT_POST
  3381.  
  3382.     lsr.l    #1,d0
  3383.     move.w    d0,AUD0LEN(a0)
  3384.     move.w    d0,AUD1LEN(a0)
  3385.     move.w    d0,AUD2LEN(a0)
  3386.     move.w    d0,AUD3LEN(a0)
  3387.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3388.     rts
  3389.  
  3390. *******************************************************************************
  3391.  
  3392. SoftInt_14bitSH:
  3393.     CONVERT_PRE
  3394.  
  3395.     move.l    d2,a0                ;get buffer ptr
  3396.     move.l    d3,a3                ;get buffer ptr
  3397.     move.l    d4,a4                ;get buffer ptr
  3398.     move.l    d5,a5                ;get buffer ptr
  3399. .loop
  3400.  
  3401. ; Left High
  3402.     move.b    (a1),d1
  3403.     lsl.l    #8,d1
  3404.     move.b    8(a1),d1
  3405.     lsl.l    #8,d1
  3406.     move.b    16(a1),d1
  3407.     lsl.l    #8,d1
  3408.     move.b    24(a1),d1
  3409.     move.l    d1,(a3)+
  3410.  
  3411. ; Left Low
  3412.     move.b    1(a1),d1
  3413.     lsr.b    #2,d1
  3414.     lsl.l    #8,d1
  3415.     move.b    9(a1),d1
  3416.     lsr.b    #2,d1
  3417.     lsl.l    #8,d1
  3418.     move.b    17(a1),d1
  3419.     lsr.b    #2,d1
  3420.     lsl.l    #8,d1
  3421.     move.b    25(a1),d1
  3422.     lsr.b    #2,d1
  3423.     move.l    d1,(a4)+
  3424.  
  3425. ; Right High
  3426.     move.b    4(a1),d1
  3427.     lsl.l    #8,d1
  3428.     move.b    12(a1),d1
  3429.     lsl.l    #8,d1
  3430.     move.b    20(a1),d1
  3431.     lsl.l    #8,d1
  3432.     move.b    28(a1),d1
  3433.     move.l    d1,(a0)+
  3434.  
  3435. ; Right Low
  3436.     move.b    5(a1),d1
  3437.     lsr.b    #2,d1
  3438.     lsl.l    #8,d1
  3439.     move.b    13(a1),d1
  3440.     lsr.b    #2,d1
  3441.     lsl.l    #8,d1
  3442.     move.b    21(a1),d1
  3443.     lsr.b    #2,d1
  3444.     lsl.l    #8,d1
  3445.     move.b    29(a1),d1
  3446.     lsr.b    #2,d1
  3447.     move.l    d1,(a5)+
  3448.  
  3449.     add.w    #32,a1
  3450.     dbf    d0,.loop
  3451.     move.l    a0,d2                ;save buffer ptr
  3452.     move.l    a3,d3                ;save buffer ptr
  3453.     move.l    a4,d4                ;save buffer ptr
  3454.     move.l    a5,d5                ;save buffer ptr
  3455.  
  3456.     CONVERT_POST
  3457.  
  3458.     lsr.l    #1,d0
  3459.     move.w    d0,AUD0LEN(a0)
  3460.     move.w    d0,AUD1LEN(a0)
  3461.     move.w    d0,AUD2LEN(a0)
  3462.     move.w    d0,AUD3LEN(a0)
  3463.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3464.     rts
  3465.  
  3466.  
  3467. *******************************************************************************
  3468.  
  3469. SoftInt_14CbitS:
  3470.     CONVERT_PRE
  3471.  
  3472.     move.l    d2,a0                ;get buffer ptr
  3473.     move.l    d3,a3                ;get buffer ptr
  3474.     move.l    d4,a4                ;get buffer ptr
  3475.     move.l    d5,a5                ;get buffer ptr
  3476.     push    a6
  3477.     move.l    p_CalibrationTable(a6),a6
  3478.     moveq    #0,d3
  3479. .loop
  3480.  
  3481. ; Left
  3482.  IFGE    __CPU-68020
  3483.     move.w    (a1),d3
  3484.     move.w    (a6,d3.l*2),d3
  3485.  ELSE
  3486.     moveq    #0,d3
  3487.     move.w    (a1),d3
  3488.      add.w    d3,d3
  3489.      move.w    (a6,d3.l),d3
  3490.  ENDC
  3491.     move.b    d3,d1
  3492.     lsl.l    #8,d1                ;xxxxAAxx
  3493.     move.w    d3,d2
  3494.     lsl.l    #8,d2                ;xxaaxxxx
  3495.  IFGE    __CPU-68020
  3496.     move.w    4(a1),d3
  3497.     move.w    (a6,d3.l*2),d3
  3498.  ELSE
  3499.     moveq    #0,d3
  3500.     move.w    4(a1),d3
  3501.      add.w    d3,d3
  3502.      move.w    (a6,d3.l),d3
  3503.  ENDC
  3504.     move.b    d3,d1
  3505.     lsl.l    #8,d1                ;xxAABBxx
  3506.     move.w    d3,d2
  3507.     lsl.l    #8,d2                ;aabbxxxx
  3508.  IFGE    __CPU-68020
  3509.     move.w    8(a1),d3
  3510.     move.w    (a6,d3.l*2),d3
  3511.  ELSE
  3512.     moveq    #0,d3
  3513.     move.w    8(a1),d3
  3514.      add.w    d3,d3
  3515.      move.w    (a6,d3.l),d3
  3516.  ENDC
  3517.     move.b    d3,d1
  3518.     lsl.l    #8,d1                ;AABBCCxx
  3519.     move.w    d3,d2                ;aabbccxx
  3520.  
  3521.  IFGE    __CPU-68020
  3522.     move.w    12(a1),d3
  3523.     move.w    (a6,d3.l*2),d3
  3524.  ELSE
  3525.     moveq    #0,d3
  3526.     move.w    12(a1),d3
  3527.      add.w    d3,d3
  3528.      move.w    (a6,d3.l),d3
  3529.  ENDC
  3530.     move.b    d3,d1                ;AABBCCDD
  3531.     lsr.w    #8,d3
  3532.     move.b    d3,d2                ;aabbccdd
  3533.  
  3534.     move.l    d1,(a4)+
  3535.     move.l    d2,(a3)+
  3536.  
  3537. ; Right
  3538.  IFGE    __CPU-68020
  3539.     move.w    2(a1),d3
  3540.     move.w    (a6,d3.l*2),d3
  3541.  ELSE
  3542.     moveq    #0,d3
  3543.     move.w    2(a1),d3
  3544.      add.w    d3,d3
  3545.      move.w    (a6,d3.l),d3
  3546.  ENDC
  3547.     move.b    d3,d1
  3548.     lsl.l    #8,d1                ;xxxxAAxx
  3549.     move.w    d3,d2
  3550.     lsl.l    #8,d2                ;xxaaxxxx
  3551.  IFGE    __CPU-68020
  3552.     move.w    6(a1),d3
  3553.     move.w    (a6,d3.l*2),d3
  3554.  ELSE
  3555.     moveq    #0,d3
  3556.     move.w    6(a1),d3
  3557.      add.w    d3,d3
  3558.      move.w    (a6,d3.l),d3
  3559.  ENDC
  3560.     move.b    d3,d1
  3561.     lsl.l    #8,d1                ;xxAABBxx
  3562.     move.w    d3,d2
  3563.     lsl.l    #8,d2                ;aabbxxxx
  3564.  IFGE    __CPU-68020
  3565.     move.w    10(a1),d3
  3566.     move.w    (a6,d3.l*2),d3
  3567.  ELSE
  3568.     moveq    #0,d3
  3569.     move.w    10(a1),d3
  3570.      add.w    d3,d3
  3571.      move.w    (a6,d3.l),d3
  3572.  ENDC
  3573.     move.b    d3,d1
  3574.     lsl.l    #8,d1                ;AABBCCxx
  3575.     move.w    d3,d2                ;aabbccxx
  3576.  
  3577.  IFGE    __CPU-68020
  3578.     move.w    14(a1),d3
  3579.     move.w    (a6,d3.l*2),d3
  3580.  ELSE
  3581.     moveq    #0,d3
  3582.     move.w    14(a1),d3
  3583.      add.w    d3,d3
  3584.      move.w    (a6,d3.l),d3
  3585.  ENDC
  3586.     move.b    d3,d1                ;AABBCCDD
  3587.     lsr.w    #8,d3
  3588.     move.b    d3,d2                ;aabbccdd
  3589.  
  3590.     move.l    d1,(a5)+
  3591.     add.w    #16,a1
  3592.     move.l    d2,(a0)+
  3593.  
  3594.     dbf    d0,.loop
  3595.     pop    a6
  3596.     move.l    a0,d2                ;save buffer ptr
  3597.     move.l    a3,d3                ;save buffer ptr
  3598.     move.l    a4,d4                ;save buffer ptr
  3599.     move.l    a5,d5                ;save buffer ptr
  3600.  
  3601.     CONVERT_POST
  3602.  
  3603.     lsr.l    #1,d0
  3604.     move.w    d0,AUD0LEN(a0)
  3605.     move.w    d0,AUD1LEN(a0)
  3606.     move.w    d0,AUD2LEN(a0)
  3607.     move.w    d0,AUD3LEN(a0)
  3608.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3609.     rts
  3610.  
  3611.  
  3612. *******************************************************************************
  3613.  
  3614. SoftInt_14CbitSH:
  3615.     CONVERT_PRE
  3616.  
  3617.     move.l    d2,a0                ;get buffer ptr
  3618.     move.l    d3,a3                ;get buffer ptr
  3619.     move.l    d4,a4                ;get buffer ptr
  3620.     move.l    d5,a5                ;get buffer ptr
  3621.     push    a6
  3622.     move.l    p_CalibrationTable(a6),a6
  3623.     moveq    #0,d3
  3624. .loop
  3625.  
  3626. ; Left
  3627.  IFGE    __CPU-68020
  3628.     move.w    (a1),d3
  3629.     move.w    (a6,d3.l*2),d3
  3630.  ELSE
  3631.     moveq    #0,d3
  3632.     move.w    (a1),d3
  3633.      add.w    d3,d3
  3634.      move.w    (a6,d3.l),d3
  3635.  ENDC
  3636.     move.b    d3,d1
  3637.     lsl.l    #8,d1                ;xxxxAAxx
  3638.     move.w    d3,d2
  3639.     lsl.l    #8,d2                ;xxaaxxxx
  3640.  IFGE    __CPU-68020
  3641.     move.w    8(a1),d3
  3642.     move.w    (a6,d3.l*2),d3
  3643.  ELSE
  3644.     moveq    #0,d3
  3645.     move.w    8(a1),d3
  3646.      add.w    d3,d3
  3647.      move.w    (a6,d3.l),d3
  3648.  ENDC
  3649.     move.b    d3,d1
  3650.     lsl.l    #8,d1                ;xxAABBxx
  3651.     move.w    d3,d2
  3652.     lsl.l    #8,d2                ;aabbxxxx
  3653.  IFGE    __CPU-68020
  3654.     move.w    16(a1),d3
  3655.     move.w    (a6,d3.l*2),d3
  3656.  ELSE
  3657.     moveq    #0,d3
  3658.     move.w    16(a1),d3
  3659.      add.w    d3,d3
  3660.      move.w    (a6,d3.l),d3
  3661.  ENDC
  3662.     move.b    d3,d1
  3663.     lsl.l    #8,d1                ;AABBCCxx
  3664.     move.w    d3,d2                ;aabbccxx
  3665.  
  3666.  IFGE    __CPU-68020
  3667.     move.w    24(a1),d3
  3668.     move.w    (a6,d3.l*2),d3
  3669.  ELSE
  3670.     moveq    #0,d3
  3671.     move.w    24(a1),d3
  3672.      add.w    d3,d3
  3673.      move.w    (a6,d3.l),d3
  3674.  ENDC
  3675.     move.b    d3,d1                ;AABBCCDD
  3676.     lsr.w    #8,d3
  3677.     move.b    d3,d2                ;aabbccdd
  3678.  
  3679.     move.l    d1,(a4)+
  3680.     move.l    d2,(a3)+
  3681.  
  3682. ; Right
  3683.  IFGE    __CPU-68020
  3684.     move.w    4(a1),d3
  3685.     move.w    (a6,d3.l*2),d3
  3686.  ELSE
  3687.     moveq    #0,d3
  3688.     move.w    4(a1),d3
  3689.      add.w    d3,d3
  3690.      move.w    (a6,d3.l),d3
  3691.  ENDC
  3692.     move.b    d3,d1
  3693.     lsl.l    #8,d1                ;xxxxAAxx
  3694.     move.w    d3,d2
  3695.     lsl.l    #8,d2                ;xxaaxxxx
  3696.  IFGE    __CPU-68020
  3697.     move.w    12(a1),d3
  3698.     move.w    (a6,d3.l*2),d3
  3699.  ELSE
  3700.     moveq    #0,d3
  3701.     move.w    12(a1),d3
  3702.      add.w    d3,d3
  3703.      move.w    (a6,d3.l),d3
  3704.  ENDC
  3705.     move.b    d3,d1
  3706.     lsl.l    #8,d1                ;xxAABBxx
  3707.     move.w    d3,d2
  3708.     lsl.l    #8,d2                ;aabbxxxx
  3709.  IFGE    __CPU-68020
  3710.     move.w    20(a1),d3
  3711.     move.w    (a6,d3.l*2),d3
  3712.  ELSE
  3713.     moveq    #0,d3
  3714.     move.w    20(a1),d3
  3715.      add.w    d3,d3
  3716.      move.w    (a6,d3.l),d3
  3717.  ENDC
  3718.     move.b    d3,d1
  3719.     lsl.l    #8,d1                ;AABBCCxx
  3720.     move.w    d3,d2                ;aabbccxx
  3721.  
  3722.  IFGE    __CPU-68020
  3723.     move.w    28(a1),d3
  3724.     move.w    (a6,d3.l*2),d3
  3725.  ELSE
  3726.     moveq    #0,d3
  3727.     move.w    28(a1),d3
  3728.      add.w    d3,d3
  3729.      move.w    (a6,d3.l),d3
  3730.  ENDC
  3731.     move.b    d3,d1                ;AABBCCDD
  3732.     lsr.w    #8,d3
  3733.     move.b    d3,d2                ;aabbccdd
  3734.  
  3735.     move.l    d1,(a5)+
  3736.     add.w    #32,a1
  3737.     move.l    d2,(a0)+
  3738.  
  3739.     dbf    d0,.loop
  3740.     pop    a6
  3741.     move.l    a0,d2                ;save buffer ptr
  3742.     move.l    a3,d3                ;save buffer ptr
  3743.     move.l    a4,d4                ;save buffer ptr
  3744.     move.l    a5,d5                ;save buffer ptr
  3745.  
  3746.     CONVERT_POST
  3747.  
  3748.     lsr.l    #1,d0
  3749.     move.w    d0,AUD0LEN(a0)
  3750.     move.w    d0,AUD1LEN(a0)
  3751.     move.w    d0,AUD2LEN(a0)
  3752.     move.w    d0,AUD3LEN(a0)
  3753.     move.w    #DMAF_SETCLR|DMAF_AUD0|DMAF_AUD1|DMAF_AUD2|DMAF_AUD3,DMACON(a0)
  3754.     rts
  3755. EndCode:
  3756.